533 Commits

Author SHA1 Message Date
Stefan Kratochwil
281615c157 Revert "lib/pico-sdk: Fix Pico SDK fetching develop picotool."
This reverts commit cbc6aed8fa.

picotool 2.1.1 has a dependency to mbedtls whose CMakeLists.txt refers
to a horrendously old and nowadays unsupported version of cmake. This
breaks the build for our project, since we use cmake 4.0.0 at the time
of writing - and this version dropped support for cmake < 3.5.

This problem has been fixed in picotool 2.2.0 which, unfortunately, is
not yet available in micropython v1.26.0.
2025-08-19 21:44:37 +02:00
f05c88b116 rp2: Allow using btree module with rp2 port
Integrate btree extmod in rp2 CMakeLists so it can be enabeled with
MICROPY_PY_BTREE=On.

Default values for DEFPSIZE and MINCACHE copied from esp8266 board.

Note: To be able to use the btree module, you must set the
MICROPY_C_HEAP_SIZE CMake option to at least 8192.
2025-08-19 20:15:33 +02:00
b40d0673a7 rp2: Fix stacks for multicore operation
Unfortunately, no way to override this from board config.
2025-08-19 20:15:33 +02:00
05d92db6f3 rp2: Modify linker script to run MP3 decoder from RAM 2025-08-19 20:15:33 +02:00
Damien George
4ce2dd2cda all: Bump version to 1.26.0.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-09 23:31:31 +10:00
Angus Gratton
593ae04eeb esp32/machine_timer: Fix machine.Timer() tick frequency on ESP32C2,C6.
Also future-proofs this code for other chips. Apart form C6 and C2, all
currently supported chips use APB clock for GPTIMER_CLK_SRC_DEFAULT.

ESP32-C2 uses 40MHz PLL but APB_CLK_FREQ was 26MHz.
ESP32-C6 uses 80MHz PLL but APB_CLK_FREQ was 40MHz.

Implementation now gets the correct frequency from ESP-IDF.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-08-07 16:55:46 +10:00
Angus Gratton
ce109af712 esp32/machine_timer: Enable timer clock source for ESP32C6.
Otherwise the PLL is not enabled.  These changes are adapted from
`timer_legacy.h` in ESP-IDF.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-08-07 16:55:23 +10:00
Damien George
d5ecda05eb ports: Allow MICROPY_PY_MACHINE_I2C_TARGET to be disabled by board cfg.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-07 10:33:26 +10:00
Damien George
255d74b5a8 renesas-ra/mpconfigport: Enable MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE.
This setting was missed in df05caea6c.  It's
needed for this port to pass its `tests/ports/renesas-ra/modtime.py` test.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-04 10:41:06 +10:00
Damien George
7c8ae78a03 lib/micropython-lib: Update submodule to latest.
This brings in:
- lora: fix SNR value in SX126x received packets
- utop: add initial implementation for ESP32
- utop: print MicroPython memory info
- utop: print IDF heap details
- urllib.urequest: add support for headers to urequest.urlopen
- aiorepl: use blocking reads for raw REPL and raw paste
- errno: add ENOTCONN constant
- logging: allow logging.exception helper to handle tracebacks
- aioble-l2cap: raise correct error if l2cap disconnects during send
- abc: add ABC base class
- aiohttp: fix partial reads by using readexactly
- aiorepl: handle stream shutdown

Signed-off-by: Damien George <damien@micropython.org>
2025-08-04 01:50:32 +10:00
Jeff Epler
c0252d73c6 py/parse: Fix missing nlr_pop call in complex path of binary_op_maybe.
Reproducer (needs to be run as one compilation unit):

    ans = (-1) ** 2.3
    aa

Fixes issue #17815.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-08-03 08:29:28 +10:00
Damien George
658a2e3dbd github/workflows: Add a CI job to build ESP32-C2 and ESP32-C6 boards.
So that all six supported SoCs are built by CI.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-02 08:53:36 +10:00
Damien George
3c9546ea09 esp32/mpconfigport: Disable I2CTarget on ESP32-C6 to reduce code size.
I2CTarget costs about 8k of flash size on ESP32-S2, and about 11k on
ESP32-C6.  The ESP32-C6 only has about 8k remaining, so disable I2CTarget
on that SoC until more flash can be made available.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-02 08:53:36 +10:00
Phil Howard
e6739fc87e rp2/rp2_flash: Add binary info for ROMFS.
This describes the ROMFS location and size in Pico SDK's binary declaration
format, so it can be read from a .uf2 file for use with various tools.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-08-02 00:36:50 +10:00
Jos Verlinde
a9dd741e66 docs/reference/mpremote: Document location of config file.
Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
2025-08-02 00:23:21 +10:00
Jos Verlinde
64b3944b01 tools/mpremote: Locate config.py location across different host OSes.
Use `platformdirs.user_config_dir()` (see
https://platformdirs.readthedocs.io/en/latest/api.html#user-config-directory)
to provide portability across many different OSes and configuration styles.

Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
2025-08-02 00:22:32 +10:00
Jos Verlinde
026a20da3e tools/mpremote: Add platformdirs dependency to requirements.txt.
Needed to easily find the user configuration file.

Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
2025-08-02 00:20:05 +10:00
Angus Gratton
907c5e9976 tests/extmod_hardware: Add basic tests for machine.Counter and Encoder.
These don't test any advanced features, just the basics.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-08-02 00:03:03 +10:00
Jonathan Hogg
641ca2eb06 docs/library/machine: Add docs for Counter and Encoder.
Add documentation for `machine.Counter` and `machine.Encoder` as currently
implemented by the esp32 port, but intended to be implemented by other
ports.

Originally authored by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com> and
Jonathan Hogg <me@jonathanhogg.com>.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2025-08-02 00:00:03 +10:00
Jonathan Hogg
327655905e esp32/modules/machine.py: Add Counter and Encoder classes.
Adds a Python override of the `machine` module, which delegates to the
built-in module and adds an implementation of `Counter` and `Encoder`,
based on the `esp32.PCNT` class.

Original implementation by: Jonathan Hogg <me@jonathanhogg.com>

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2025-08-01 23:45:18 +10:00
Jonathan Hogg
e54553c496 docs/esp32: Add documentation for esp32.PCNT.
Document the new `esp32.PCNT` class for hardware pulse counting.

Originally authored by: Jonathan Hogg <me@jonathanhogg.com>

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2025-08-01 23:45:18 +10:00
Jonathan Hogg
c3f3339c87 esp32/modesp32: Add esp32.PCNT class.
Add a new `esp32.PCNT` class that provides complete, low-level support to
the ESP32 PCNT pulse counting hardware units.

This can be used as a building block to implement the higher-level
`machine.Counter` and `machine.Encoder` classes.

This is enabled by default on all OG, S2, S3, C6 boards, but not on C3 (as
the PCNT peripheral is not supported).

Original implementation by: Jonathan Hogg <me@jonathanhogg.com>

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-08-01 23:45:18 +10:00
Damien George
bf6f229cf3 docs/library: Document the new machine.I2CTarget class.
With some working examples that show how to use all the features.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
277b615f26 tests/multi_extmod: Add I2CTarget multi tests.
These require two boards wired together, SCL-SCL and SDA-SDA.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
6558d519a2 tests/extmod_hardware: Add self unittest for I2CTarget.
This test uses a SoftI2C controller wired to an I2CTarget on the one board,
and tests all functionality of the I2CTarget class.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
7bc83afee2 esp32/machine_i2c_target: Implement I2CTarget class.
Only soft IRQs are supported.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
ac5b1bce99 esp32/machine_i2c: Factor default pin macros to header file.
So the implementation of I2CTarget can use them.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
robert-hh
79d182deb2 samd/machine_i2c_target: Support I2C target mode.
Supporting readfrom_mem*(). writeto_mem() and a set of IRQs.  Enabled by
default for SAMD51 devices and SAMD21 devices with external flash.

Tested with ItsyBitsy M4 and ItsyBitsy M0 with both on-board SoftI2C and a
RP2 Pico as controller.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: robert-hh <robert@hammelrath.com>
2025-08-01 23:03:17 +10:00
robert-hh
5c78762c16 mimxrt/machine_i2c_target: Support I2C target mode.
The functionality is similar to the RP2 implementation.  The supported
address size is 7 bit.  In order to achieve a sufficient response, the
target I2C IRQ handler has to run from RAM, causing much more code moved to
RAM than required.

Tested with Teensy 4.1, MIMXRT1021EVK, MIMXRT1011EVK and MIMXRT1170, using
both a On-Board SoftI2C as controller and a RP2 Pico as external
controller.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: robert-hh <robert@hammelrath.com>
2025-08-01 23:03:17 +10:00
Damien George
67a442d8fa alif/machine_i2c: Allow changing I2C SCL/SDA pins.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
6e72cae619 alif/machine_i2c_target: Implement I2CTarget class.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
0c50343145 zephyr/machine_i2c_target: Implement I2CTarget class.
Tested and working on rpi_pico and nucleo_wb55rg.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
1839340dda rp2/machine_i2c_target: Implement I2CTarget class.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
56d2b47370 rp2/machine_i2c: Factor default pin macros to header file.
So they can be reused by the I2CTarget implementation.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
01e570a347 stm32/machine_i2c_target: Implement I2CTarget class.
Works, tested on PYBV10, PYBD_SF2 and PYBD_SF6:

    buf = bytearray(16)
    machine.I2CTargetMemory("X", addr=67, mem=buf)

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
78d16672e1 stm32/i2cslave: Account for slow addr_match callback.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
2443878bd9 stm32/i2cslave: Support i2c_slave_process_tx_end callback on F4.
The rounds out the F4 implementation to match the other supported MCUs.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
17d0449ac8 stm32/i2cslave: Add functions to read/write I2C data.
Instead of requiring the callback to consume/provide the data.  This allows
the data to be consumed/provided later on, which will stretch the I2C clock
until that occurs.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
a4ca42f094 stm32/i2cslave: Change irq handler name to i2c_slave_irq_handler.
Remove the "ev" part, so this handler can be generalised to also handle
error IRQs.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
9b1778fc77 stm32/i2c: Move I2C IRQ handlers from stm32_it.c to i2c.c.
And add MP_STATIC_ASSERT to statically check that the IRQ names are correct
on the MCU that it's compiled for.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Damien George
1b578fe2c0 extmod/machine_i2c_target: Add new machine.I2CTarget class.
This commit implements a generic I2C target/peripheral/"slave" device,
called `machine.I2CTarget`.  It can work in two separate modes:

- A general device with interrupts/events/callbacks for low-level I2C
  operations like address match, read request and stop.

- A memory device that allows reading/writing a specific region of memory
  (or "registers") on the target I2C device.

To make a memory device is very simple:

    from machine import I2CTarget

    mem = bytearray(8)
    i2c = I2CTarget(addr=67, mem=mem)

That's all that's needed to start the I2C target.  From then on it will
respond to any I2C controller on the bus, allowing reads and writes to the
mem bytearray.

It's also possible to register to receive events.  For example to be
notified when the memory is read/written:

    from machine import I2CTarget

    def irq_handler(i2c_target):
        flags = i2c_target.irq().flags()
        if flags & I2CTarget.IRQ_END_READ:
            print("controller read target at addr", i2c_target.memaddr)
        if flags & I2CTarget.IRQ_END_WRITE:
            print("controller wrote target at addr", i2c_target.memaddr)

    mem = bytearray(8)
    i2c = I2CTarget(addr=67, mem=mem)
    i2c.irq(irq_handler)

Instead of a memory device, an arbitrary I2C device can be implemented
using all the events (see docs).

This is based on the discussion in #3935.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 23:03:17 +10:00
Koudai Aono
ab7c5a1733 docs/library/btree: Fix method links to explicitly specify class.
So they don't clash with other potential references.

Signed-off-by: Koudai Aono <koxudaxi@gmail.com>
2025-08-01 22:58:26 +10:00
root
769453c750 rp2/rp2_pio: Fix use of PIO2 in prog data structure.
The RP2350 PIO2 State Machines (8, 9, 10, 11) did not work.  The data
structure used to pass the PIO arguments was missing an entry for PIO2,
thus causing the PIO2 instances to write wrong data to wrong locations.

Fixes issue #17509.

Signed-off-by: Matt Westveld <github@intergalacticmicro.com>
2025-08-01 22:38:00 +10:00
Dryw Wade
c9b52b2b7f rp2/CMakeLists.txt: Fix flash size check logic.
Follow up to 6bfb83e30a, if the variable
`PICO_FLASH_SIZE_BYTES` is not a numeric constant, eg "(2 * 1024 * 1024)",
then it won't pass the GREATER check.  So change the if logic to just test
if it's defined.

Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
2025-08-01 16:20:49 +10:00
Damien George
a9a606bf5d docs/library/rp2.StateMachine: Add a note about PIO in and jmp pins.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 15:10:15 +10:00
Damien George
41987c6cf4 rp2/rp2_pio: Configure jmp_pin for PIO use if it's isolation is set.
Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 15:10:15 +10:00
Jos Verlinde
dea949e860 tools/mpremote: Update ESPxxx detection for USB-CDC ports.
Detection of ESP-XX devices was based on just the names of the USB driver
name, and did not account for the switch of the newer ESP-xx devices to
USB-CDC.  On Windows this caused unwanted/unneeded resets as the DTR/RTS
signals are also used for automatic device reset over USB-CDC.  See
https://github.com/micropython/micropython/issues/9659#issuecomment-3124704572

This commit uses the Espressif registered VID 0x303A to detect USB-CDC
ports, to enable the same DTR/RTS settings as used on the UART-USB
connection.

Also improved the robustness of the code using `getattr()`.

Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
2025-08-01 14:58:20 +10:00
Jos Verlinde
4ba626ab5a tools/mpremote: Fix errno.ENOTBLK attribute error on Windows.
Not all errors defined in stdlib errno are available on Windows.
Specifically, errno.ENOTBLK is not.

Fixes issue #17773.

Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
2025-08-01 14:52:59 +10:00
Chris Webb
953da2080e tests/micropython: Test that viper offset stores don't clobber base reg.
When running the viper boundary tests, assert that the offset stores don't
clobber the base register, which is saved and temporarily modified on some
architectures.

Signed-off-by: Chris Webb <chris@arachsys.com>
2025-08-01 14:17:49 +10:00
Chris Webb
f39434e9fb py/asmthumb: Don't corrupt base register in large offset store.
asm_thumb_store_reg_reg_offset() modifies the base register when storing
with a large offset which triggers the generic path. If a variable lives
in that register, this corrupts it. Fix this by saving the base register
on the stack before modifying it.

Signed-off-by: Chris Webb <chris@arachsys.com>
2025-08-01 14:15:39 +10:00
Yoctopuce dev
69ead7d98e py/parse: Add support for math module constants and float folding.
Add a new MICROPY_COMP_CONST_FLOAT feature, enabled by in mpy-cross and
when compiling with MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES.  The new
feature leverages the code of MICROPY_COMP_CONST_FOLDING to support folding
of floating point constants.

If MICROPY_COMP_MODULE_CONST is defined as well, math module constants are
made available at compile time. For example:

    _DEG_TO_GRADIANT = const(math.pi / 180)
    _INVALID_VALUE = const(math.nan)

A few corner cases had to be handled:
- The float const folding code should not fold expressions resulting into
  complex results, as the mpy parser for complex immediates has
  limitations.
- The constant generation code must distinguish between -0.0 and 0.0, which
  are different even if C consider them as ==.

This change removes previous limitations on the use of `const()`
expressions that would result in floating point number, so the test cases
of micropython/const_error have to be updated.

Additional test cases have been added to cover the new repr() code (from a
previous commit).  A few other simple test cases have been added to handle
the use of floats in `const()` expressions, but the float folding code
itself is also tested when running general float test cases, as float
expressions often get resolved at compile-time (with this change).

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-08-01 13:35:44 +10:00
SiZiOUS
f67a370311 embed/port: Fix alloca include for Windows platforms.
When building the embedded port on MinGW-w64, I receive the following
error:

    fatal error: alloca.h: No such file or directory

MinGW-w64 (used on MSYS2) doesn't include `alloca.h`, but `alloca()` is
provided via `malloc.h` instead.  And this fix is also needed for other
Windows build systems.

Signed-off-by: SiZiOUS <sizious@gmail.com>
2025-08-01 12:01:37 +10:00
Damien George
f8f6d71940 nrf/drivers/bluetooth: Change soft-device download URL to self hosted.
The existing URLs have started to return a HTTP 403.  The simplest way
around this is to host the files at micropython.org, and point to them from
the download script.

The soft-device files have been retrieved from:
- https://www.nordicsemi.com/Products/Development-software/s110/download
- https://www.nordicsemi.com/Products/Development-software/s132/download
- https://www.nordicsemi.com/Products/Development-software/s140/download

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 11:34:42 +10:00
Damien George
947d5448b4 tests/cpydiff: Remove passing types_float_rounding test.
Since commit dbbaa959c8, this test now
produces the same output on MicroPython as CPython does, namely -1e+01.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 11:13:12 +10:00
Damien George
97d56527a0 github/workflows: Build unix port for docs and run workflow more often.
The unix port is needed to build the docs, due to the cpydiff tests which
run both CPython and MicroPython (unix port).  That was previously not
failing the CI because the output from MicroPython was:

    /bin/sh: 1: ../ports/unix/build-standard/micropython: not found

which doesn't match the CPython output for any of the cpydiff tests, and so
it was considered a "pass" in terms of the output differing.

Also, run the docs workflow when py/ or tests/cpydiff/ changes, because the
cpydiff results may change when the core code changes.

Signed-off-by: Damien George <damien@micropython.org>
2025-08-01 11:04:01 +10:00
Yoctopuce dev
dbbaa959c8 py/formatfloat: Improve accuracy of float formatting code.
Following discussions in PR #16666, this commit updates the float
formatting code to improve the `repr` reversibility, i.e. the percentage of
valid floating point numbers that do parse back to the same number when
formatted by `repr` (in CPython it's 100%).

This new code offers a choice of 3 float conversion methods, depending on
the desired tradeoff between code size and conversion precision:

- BASIC method is the smallest code footprint

- APPROX method uses an iterative method to approximate the exact
  representation, which is a bit slower but but does not have a big impact
  on code size.  It provides `repr` reversibility on >99.8% of the cases in
  double precision, and on >98.5% in single precision (except with REPR_C,
  where reversibility is 100% as the last two bits are not taken into
  account).

- EXACT method uses higher-precision floats during conversion, which
  provides perfect results but has a higher impact on code size.  It is
  faster than APPROX method, and faster than the CPython equivalent
  implementation.  It is however not available on all compilers when using
  FLOAT_IMPL_DOUBLE.

Here is the table comparing the impact of the three conversion methods on
code footprint on PYBV10 (using single-precision floats) and reversibility
rate for both single-precision and double-precision floats.  The table
includes current situation as a baseline for the comparison:

              PYBV10  REPR_C   FLOAT  DOUBLE
    current = 364688   12.9%   27.6%   37.9%
    basic   = 364812   85.6%   60.5%   85.7%
    approx  = 365080  100.0%   98.5%   99.8%
    exact   = 366408  100.0%  100.0%  100.0%

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-08-01 00:47:33 +10:00
Yoctopuce dev
e4e1c9f413 py/parsenum: Refactor float parsing code.
This commit extracts from the current float parsing code two functions
which could be reused elsewhere in MicroPython.

The code used to multiply a float x by a power of 10 is also simplified by
applying the binary exponent separately from the power of 5.  This avoids
the risk of overflow in the intermediate stage, before multiplying by x.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-08-01 00:47:33 +10:00
Damien George
ffa98cb014 webassembly/proxy_js: Reuse JsProxy ref if object matches.
This reduces memory use by reusing objects, and improves identity/equality
relationships of JavaScript objects on the Python side.

In 77bd8fe5b8 PyProxy's were reused when the
same Python object was proxied across to JavaScript.  This commit does the
same thing but for JsProxy's going from JS to Python.  If an existing
JsProxy reference exists for the JS object about to be proxied across, then
it's reused.

This helps reduce the number of alive objects (memory use), and, more
importantly, improves equality relationships of JavaScript objects on the
Python side.  Eg we now get, on the Python side:

    import js

    print(js.Object == js.Object)

that prints True.  Previously it was False.

Note that this change does not make identity work with `is`, for example
`js.Object is js.Object` is actually False.  With more work that could be
made True but for now we leave that as-is.

The behaviour with this commit matches Pyodide semantics.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 11:40:50 +10:00
Damien George
813f0c1cb9 webassembly/objjsproxy: Implement equality for JsProxy objects.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 11:40:03 +10:00
Damien George
241ee163c0 py/objboundmeth: Add option to use mp_is_equal instead of == comparison.
This option is needed for ports such as webassembly where objects are
proxied and can be identical without being the same C pointer.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 11:38:35 +10:00
Angus Gratton
fdbd23268d tests/run-multitests.py: Escape encoding errors instead of crashing.
It's possible for a test to output non-ASCII characters (for example, due
to a hard fault or serial noise or memory corruption). Rather than crashing
the test runner, backslash escape those characters and treat them as
program output.

Refactors the string encoding step to a single helper to avoid copy-paste.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-31 11:17:13 +10:00
Angus Gratton
4bdf2a2dc0 tests/multi_bluetooth: Extend the deep sleep test timeout.
As per comment, if a boot.py is present that connects to Wi-Fi then waking
can take a little longer.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-31 11:15:03 +10:00
Damien George
ff6491ded0 tests/run-natmodtests.py: Automatically skip tests that are too large.
This follows a similar change made for `run-tests.py` in commit
229104558f.  The change here uses the same
logic to detect if a natmod test is too big for the target (eg overflows
(I)RAM loading the native .mpy), by printing "START TEST" at the start of
the test.

Typical output is now something like this:

    ...
    pass  extmod/random_basic.py
    pass  extmod/random_extra_float.py
    pass  extmod/random_extra.py
    SKIP  extmod/random_seed_default.py
    LRGE  extmod/re1.py
    SKIP  extmod/re_debug.py
    pass  extmod/re_error.py
    pass  extmod/re_group.py
    pass  extmod/re_groups.py
    ...

and the tests that are too large are reported at the end, and written to
the `_result.json` file.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 11:07:50 +10:00
Damien George
a9b038a57e examples/bluetooth/ble_advertising.py: Fix decoding UUIDs.
The UUID32 case was incorrect: first, the "<d" should have been "<I", and
second, the UUID constructor treats integer arguments as UUID16.  So this
UUID32 case needs to pass in the actual data bytes.

And then it's simpler to just make all cases pass in the data bytes.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 11:02:41 +10:00
Damien George
6a8c45b6c4 docs/library/bluetooth: Document all allowed args to UUID constructor.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 11:02:41 +10:00
Damien George
4360da1684 zephyr/mpconfigport: Use MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES.
This commit adjusts the configuration of the standard zephyr build to use
MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES.  That's a lot cleaner than
explicitly enabling/disabling options, and allows boards to more easily
fine-tune the settings, eg select a different feature level.

Features that are now enabled are:
- async/await keyword support
- `filter`, `property` and `reversed` builtins
- `range` attributes
- `str.count()` method
- `array` module with `array.array` object
- `collections` module with `collections.namedtuple` object
- `struct` module with everything
- `id = const()` and constant folding in the compiler

Bulding qemu_cortex_m3, the code size was originally:

    Memory region         Used Size  Region Size  %age Used
               FLASH:      193864 B       256 KB     73.95%
                 RAM:       61992 B        64 KB     94.59%

and with this commit it is now:

    Memory region         Used Size  Region Size  %age Used
               FLASH:      200698 B       256 KB     76.56%
                 RAM:       61992 B        64 KB     94.59%

That's a mild increase of +6834 bytes flash usage for a good selection of
new features.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 10:48:56 +10:00
Damien George
68434b4be7 zephyr/mpconfigport_minimal: Use MICROPY_CONFIG_ROM_LEVEL_MINIMUM.
This commit adjusts the configuration of the minimal zephyr build to use
MICROPY_CONFIG_ROM_LEVEL_MINIMUM.  That's a lot cleaner than explicitly
enabling/disabling options.

Prior to this change the minimal build for qemu_cortex_m3 had size:

    Memory region         Used Size  Region Size  %age Used
               FLASH:      114436 B       256 KB     43.65%
                 RAM:       26320 B        64 KB     40.16%

and had the following test results (running using the CI settings, ie
`-d basics float --exclude inf_nan_arith`):

    352 tests performed (7092 individual testcases)
    352 tests passed
    254 tests skipped: ...

With the changes here the qemu_cortex_m3 size is now:

    Memory region         Used Size  Region Size  %age Used
               FLASH:       99428 B       256 KB     37.93%
                 RAM:       26312 B        64 KB     40.15%

That's a good decrease of about 15k firmware size.  And the test suite
still passes with:

    342 tests performed (6776 individual testcases)
    341 tests passed
    265 tests skipped: ...

Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 10:48:56 +10:00
Damien George
135c1cc7cd extmod/modtls_mbedtls: Do gc_collect and retry ssl_init on any error.
Contrary to the docs, mbedtls can return more than just
MBEDTLS_ERR_SSL_ALLOC_FAILED when `mbedtls_ssl_setup()` fails.  At least
MBEDTLS_ERR_MD_ALLOC_FAILED was also seen on ESP32_GENERIC, but there
could possibly be other error codes.

To cover all these codes, just check if `ret` is non-0, and in that case
do a `gc_collect()` and retry the init.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-31 10:46:47 +10:00
Yanfeng Liu
ab4af2c1a6 py/mphal: Add stddef.h header for size_t.
This includes "stddef.h" for `size_t` to resolve NuttX integration build
issues.

Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
2025-07-30 11:47:43 +10:00
Angus Gratton
d4399b3230 esp32: Fix first line ESP32-C2 serial output after reset or deepsleep.
ESP32-C2 ROM prints at 74880bps (same as ESP8266), so need a newline
before first MicroPython output to avoid it being appended on end of
a line of noise.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-30 10:51:29 +10:00
Angus Gratton
77c9eb7795 esp32: Add "Free RAM" optimisation config flags.
This is necessary for ESP32-C2 Wi-Fi & BT to work reliably (and for TLS to
work at all). On IDF 5.4.2 the free static RAM goes from 60KB to 100KB, and
there will also be a reduction in lwIP & Wi-Fi memory use at runtime.

The performance trade-off seems low for most use cases, although it will
probably be significant for certain combinations of load (i.e. heavy
TCP/IP, heavy BT throughput, and some peripheral driver functions).

Added as a set of config flags because this is potentially useful on other
SoCs where the goal is to maximise RAM available for MicroPython.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-30 10:51:29 +10:00
TianShuang Ke
ca9916968c esp32: Add support for ESP32-C2 (aka ESP8684).
Includes:
esp32/esp32c2: Adapt to target chip ESP32C2.
esp32/esp32c2: Fix heap size is too small to enable Bluetooth.

Signed-off-by: TianShuangKe <qinyun575@gmail.com>
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-30 10:51:29 +10:00
Anson Mansfield
88cb6bc818 tests/run-internalbench.py: Allow running internalbench on hardware.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-29 11:49:10 +10:00
Anson Mansfield
b9d6d6af4b tests/internal_bench/var: Benchmark descriptor access.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-29 10:08:53 +10:00
Anson Mansfield
c3e77ad6db tests/internal_bench/class_create: Benchmark class creation.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-29 10:08:53 +10:00
Anson Mansfield
d5dc554742 docs: Document PEP487 __set_name__ implementation.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-29 09:44:26 +10:00
Anson Mansfield
4412753f0c py/objtype: Add support for PEP487 __set_name__.
This commit adds support for the `__set_name__` data model method specified
by PEP487 - Simpler customisation of class creation.

This includes support for methods that mutate the owner class, and avoids
the naive modify-while-iterating hazard possible in a naive implementation
like micropython/micropython#15503.

Note that based on the benchmarks in micropython/micropython#16825, this is
also as fast or faster than the naive implementation, thanks to clever data
layout in `setname_list_t`, and the way this allows the capture step to run
during an existing loop through the class dict.

Other rejected approaches for dealing with the hazard include:

- python/cpython#72983
During the implementation of this feature for MicroPython, it was
discovered that some versions of CPython also have this naive hazard.
CPython resolved this bug in BPO-28797 and now makes a complete flat copy
of the class's dict to iterate.  This design decision doesn't make much
sense for a microcontroller though, even if it's perfectly reasonable in
the desktop world where memcpy might actually be cheaper than a
hard-to-branch-predict conditional; and it's also motivated in their case
by error-tracing considerations.

- micropython/micropython#16816
This is an equivalent implementation to CPython's approach that places this
copy directly on the stack; however it is both slower and has larger code
size than the approach taken here.

- micropython/micropython#15503
The simplest implementation is to just not worry about it and let the user
face the consequences if they mutate the owner class.  That's not a very
friendly behavior, though, and it's not actually much more performant than
this implementation on either time or code size.

- micropython/micropython#17693
Another alternative is to do the same as #15503 but leverage MicroPython's
existing `is_fixed` field in its dict type to convert attempted mutations
of the owner dict into `AttributeError`s.  This is safer than just leaving
the open hazard, but there's still important use-cases for owner-mutating
descriptors, and the performance gain is small enough that it isn't worth
missing support for those cases.

- combined micropython/micropython#17693 with this
Another version of this feature used a new feature define,
`MICROPY_PY_METACLASSES_LITE`, to control whether this algorithm or the
naive version is used.  This was rejected in favor of simplicity, based on
the very limited performance margin the naive version has (which in some
cases even goes _against_ it).

Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-29 09:41:24 +10:00
Anson Mansfield
82db5c81e0 tests/basics: Add tests for PEP487 __set_name__.
Including the stochastic tests needed to guarantee sensitivity to the
potential iterate-while-modifying hazard a naive implementation might have.

Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-29 09:41:10 +10:00
Yoctopuce dev
3a72f95919 py/objint_longlong: Fix longlong interoperability with floats.
Current longlong implementation does not allow a float as RHS of mathematic
operators, as it lacks the delegation code present in mpz.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-07-29 01:14:35 +10:00
Yoctopuce dev
3c69277ba9 py/objint_longlong: Fix overflow check in mp_obj_int_get_checked.
This is to fix an outstanding TODO.  The test cases is using a range as
this will exist in all builds, but `mp_obj_get_int` is used in many
different parts of code where an overflow is more likely to occur.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-07-29 00:27:01 +10:00
Jeff Epler
062e82a7cd py/objint_mpz: Fix pow3 where third argument is zero.
This finding is based on fuzzing MicroPython.  I manually minimized the
test case it provided.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-28 23:58:46 +10:00
Christian Lang
ebc9525c95 rp2/modmachine: Do not use deprecated XOSC_MHZ and XOSC_KHZ.
XOSC_MHZ and XOSC_KHZ may not be defined if we use a custom XIN clock
by defining PLL_SYS_REFDIV etc. calculated by vcocalc.py.

Signed-off-by: Christian Lang <lang.chr86@gmail.com>
2025-07-25 11:25:24 +10:00
Jeff Epler
ab620f4084 py/mpprint: Fix printing pointers with upper bit set.
On a build like nanbox, `mp_uint_t` is wider than `u/intptr_t`.  Using a
signed type for fetching pointer values resulted in erroneous results: like
`<function f at 0xfffffffff7a60bc0>` instead of
`<function f at 0xf7a60bc0>`.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 11:01:42 +10:00
Jeff Epler
87b7a9d734 stm32: Add casts when printing small integers.
All these arguments are of type `mp_{u,}int_t`, but the actual value is
always a small integer.  Cast it so that it can format with the `%d/%u`
formatter.

Before, the compiler plugin produced an error in the PYBD_SF6 build, which
is a nanboxing build with 64-bit ints.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 11:01:16 +10:00
Jeff Epler
ee4f27affa py/objcell: Fix printing of cell ID/pointer.
On the nanbox build, `o->obj` is a 64-bit type but `%p` formats a 32-bit
type, leading to undefined behavior.

Print the cell's ID as a hex integer instead.

This location was found using an experimental gcc plugin for `mp_printf`
error checking.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 11:00:41 +10:00
Jeff Epler
4495610f8d shared/netutils: Cast the ticks value before printing.
Before, the compiler plugin produced an error in the PYBD_SF6 build, which
is a nanboxing build with 64-bit ints.

I made the decision here to cast the value even though some significant
bits might be lost after 49.7 days.  However, the format used is "% 8d",
which produces a consistent width output for small ticks values (up to
about 1.1 days).  I judged that it was more valuable to preserve the fixed
width display than to accurately represent long time periods.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 11:00:08 +10:00
Jeff Epler
2d93909ebe extmod/modlwip: Print timeout with correct format string.
As timeout is of type `mp_uint_t`, it must be printed with UINT_FMT.

Before, the compiler plugin produced an error in the PYBD_SF6 build, which
is a nanboxing build with 64-bit ints.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:59:51 +10:00
Jeff Epler
18a835e9b4 examples/usercmodule: Cast arguments for printf.
These locations were found using an experimental gcc plugin for `mp_printf`
error checking.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:59:28 +10:00
Jeff Epler
338ca3b68f unix/coverage: Remove unused printf arguments.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:59:17 +10:00
Jeff Epler
aa9152ae0c unix/coverage: Provide argmuents of expected integer types.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:59:04 +10:00
Jeff Epler
db7e935917 unix/coverage: Cast values to int for format printing.
During the coverage test, all the values encountered are within the range
of `%d`.

These locations were found using an experimental gcc plugin for `mp_printf`
error checking.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:58:24 +10:00
Jeff Epler
61006d8016 unix/coverage: Cast values to fit %x formatting code.
This fixes the following diagnostic produced by the plugin:

    error: argument 3: Format ‘%x’ requires a ‘int’ or
        ‘unsigned int’ (32 bits), not ‘long unsigned int’ [size 64]
        [-Werror=format=]

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:57:59 +10:00
Jeff Epler
a06857a11a unix/coverage: Cast type names to qstr explicitly.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:57:54 +10:00
Jeff Epler
a1a8eacdce unix/coverage: Avoid type checking an invalid string.
We still want this not to crash a runtime but the new static checker
wouldn't like it.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:57:39 +10:00
Jeff Epler
d0d111356f py: Fix mp_printf integer size mismatches.
The type of the argument must match the format string.  Add casts to ensure
that they do.

It's possible that casting from `size_t` to `unsigned` loses the correct
values by masking off upper bits, but it seems likely that the quantities
involved in practice are small enough that the `%u` formatter (32 bits on
most platforms, 16 on pic16bit) will in fact hold the correct value.

The alternative, casting to a wider type, adds code size.

These locations were found using an experimental gcc plugin for `mp_printf`
error checking, cross-building for x64 windows on Linux.

In one case there was already a cast, but it was written incorrectly and
did not have the intended effect.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:56:57 +10:00
Jeff Epler
519cba4d05 py: Cast type names to qstr explicitly.
The name field of type objects is of type `uint16_t` for efficiency, but
when the type is passed to `mp_printf` it must be cast explicitly to type
`qstr`.

These locations were found using an experimental gcc plugin for `mp_printf`
error checking, cross-building for x64 windows on Linux.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:56:02 +10:00
Jeff Epler
7493275918 py/mpconfig,ports: Define new HEX_FMT formatting macro.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:55:28 +10:00
Jeff Epler
0c8d35b322 ports: Eliminate define of {U,}INT_FMT where redundant.
The default definition in `py/mpconfig.h` for 32-bit architectures is
`%u/%d`, so these can be removed.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-25 10:54:27 +10:00
Angus Gratton
096ff8b9ee tests/micropython: Rename viper boundary tests that depend on big int.
These tests all depend on generating arbitrarily long (>64-bit) integers.

It would be possible to have these tests work in this case I think, as the
results are always masked to shorter values.  But quite fiddly.  So just
rename them so they are automatically skipped if the target doesn't have
big int support.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-24 15:50:34 +10:00
Angus Gratton
5d9ef6bfb6 py/objint_longlong: Fix left shift of negative values.
Previous comment was wrong, left shifting a negative value is UB in C. Use
the same approach as small int shifts (from runtime.c).

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-24 15:50:00 +10:00
Damien George
3185bb5827 py/obj: Add new type flag to indicate subscr accepts slice-on-stack.
The recently merged 5e9189d6d1 now allows
temporary slices to be allocated on the C stack, which is much better than
allocating them on the GC heap.

Unfortunately there are cases where the C-allocated slice can escape and be
retained as an object, which leads to crashes (because that object points
to the C stack which now has other values on it).

The fix here is to add a new `MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE`.
Native types should set this flag if their subscr method is guaranteed not
to hold on to a reference of the slice object.

Fixes issue #17733 (see also #17723).

Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 14:55:34 +10:00
Damien George
45aa65b67d webassembly/objjsproxy: Fix binding of self to JavaScript methods.
Fixes a bug in the binding of self/this to JavaScript methods.

The new semantics match Pyodide's behaviour, at least for the included
tests.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 14:38:08 +10:00
Damien George
9b61bb93f9 webassembly/proxy_c: Provide constants for fixed JsProxy refs.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 14:37:30 +10:00
Damien George
f6e23fdef1 tools/ci.sh: Test building all natmod examples with all ARM-M archs.
And run both armv6m and armv7m under qemu.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 14:01:45 +10:00
Damien George
e750ecff70 qemu/Makefile: Allow passing flags to test_natmod via RUN_TESTS_EXTRA.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 14:01:45 +10:00
Damien George
bba15e0a0b examples/natmod: Use LINK_RUNTIME=1 when building for armv6m.
To get division helper functions, eg `__aeabi_uidiv`, `__aeabi_idiv` and
`__aeabi_uidivmod`.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 14:01:45 +10:00
Phil Howard
cbc6aed8fa lib/pico-sdk: Fix Pico SDK fetching develop picotool.
SDK 2.1.1 shipped with PICOTOOL_FETCH_FROM_GIT configured to fetch the
"develop" branch. This broke downstream CI, which was trusting Pico
SDK to fetch the correct version.

RPi have added a "2.1.1-correct-picotool" tag which fixes this.

lib/pico-sdk: Bump to "2.1.1-correct-picotool" tag.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-07-24 13:51:02 +10:00
Andrew Leech
bc77b27bad unix/mpthreadport: Ensure consistent type of PTHREAD_STACK_MIN.
It seems GCC 14 got stricter with warn/errs like -Wsign-compare and types a
"bare number" as a long int that can't be compared to a (unsigned) size_t.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-07-24 13:29:36 +10:00
Damien George
7729e80fdd all: Go back to using default ruff quote style.
Commit dc2fcfcc55 seems to have accidentally
changed the ruff quote style to "preserve", instead of keeping it at the
default which is "double".

Put it back to the default and update relevant .py files with this rule.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 12:48:18 +10:00
Damien George
6a4306a0df unix/mpconfigport: Include time.h to get definition of time_t.
Without this there's a build error on macOS (at least).  This was likely
due to a combination of 9b7d85227e and
df05caea6c.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-24 11:42:53 +10:00
Yoctopuce dev
8b3439e26c unix/variants/longlong: Use REPR_C on this variant.
There is currently no build using REPR_C in the unix CI tests.  As
discussed in PR #16953, this is something that combines well with the
longlong build.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-07-24 11:07:30 +10:00
Yoctopuce dev
d6876e2273 py/obj: Fix REPR_C bias toward zero.
Current implementation of REPR_C works by clearing the two lower bits of
the mantissa to zero.  As this happens after each floating point operation,
this tends to bias floating point numbers towards zero, causing decimals
like .9997 instead of rounded numbers.  This is visible in test cases
involving repeated computations, such as `tests/misc/rge_sm.py` for
instance.

The suggested fix fills in the missing bits by copying the previous two
bits.  Although this cannot recreate missing information, it fixes the bias
by inserting plausible values for the lost bits, at a relatively low cost.

Some float tests involving irrational numbers have to be softened in case
of REPR_C, as the 30 bits are not always enough to fulfill the expectations
of the original test, and the change may randomly affect the last digits.
Such cases have been made explicit by testing for REPR_C or by adding a
clear comment.

The perf_test fft code was also missing a call to round() before casting a
log_2 operation to int, which was causing a failure due to a last-decimal
change.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-07-24 11:07:30 +10:00
Jeff Epler
59ee59901b extmod/vfs_posix: Add MICROPY_VFS_POSIX_WRITABLE option.
When this configuration flag is set, VfsPosix instances can be written.
Otherwise, they will always be created "read only".

This flag is useful when fuzzing micropython: Without VfsPosix, the fuzzing
input script cannot be read; but with writable VfsPosix, fuzzing scripts
can potentially perform undesired operations on the host filesystem.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-24 10:39:41 +10:00
Jeff Epler
3c603f7baf extmod/vfs_posix: Add additional readonly checks.
Otherwise operations such as unlink can be performed on a nominally
read-only VfsPosix.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-24 10:39:25 +10:00
Jeff Epler
d79000df70 tests/extmod: Add (failing) test for VfsPosix in readonly mode.
I noticed that operations such as unlink could be performed on a nominally
read-only VfsPosix.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-24 10:39:23 +10:00
Andrew Leech
6515cd05f1 extmod/vfs_lfsx: Allow overriding the LFS2 on-disk version format.
Back in LFS2 version 2.6 they updated the on-disk version from 2.0 to 2.1
which broke back compatibility (aka older versions could no long read new
version disk format), see
https://github.com/littlefs-project/littlefs/releases/tag/v2.6.0

Then in LFS2 v2.7 an optional `config->disk_version` was added to force the
library to use an older disk format instead, see:
https://github.com/littlefs-project/littlefs/releases/tag/v2.7.0

This commit simply exposes `config->disk_version` as a compile time option
if LFS2_MULTIVERSION is set, otherwise there is no change in behavior.
This is Useful for compatibility with older LFS versions.

Note: LFS2_MULTIVERSION needs to be defined at the make / CFLAGS level,
setting it in mpconfigboard.h doesn't work as it's not included in the
`lfs2.c` file in any way.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-07-23 15:51:08 +10:00
Angus Gratton
28082d1d25 extmod/mbedtls: Undefine ARRAY_SIZE if defined by platform.
This is an annoying regression caused by including mpconfig.h in 36922df -
the mimxrt platform headers define ARRAY_SIZE and mbedtls also defines in
some source files, using a different parameter name which is a warning in
gcc.

Technically mimxrt SDK is to blame here, but as this isn't a named warning
in gcc the only way to work around it in the mimxrt port would be to
disable all warnings when building this particular mbedTLS source file.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-23 15:47:17 +10:00
Angus Gratton
89f9ee9d7c tests/multi_net: Update DTLS multi-net test.
The original version of this test had to exchange a 1 byte UDP packet
before the DTLS handshake. This is no longer needed due to MSG_PEEK
support.

The test also doesn't work with HelloVerify enabled, as the first
connection attempt always fails with an
MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED result. Anticipate this by listening
for the client twice on the server side.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-23 15:47:16 +10:00
Angus Gratton
9b7d85227e extmod/mbedtls: Implement recommended DTLS features, make optional.
- DTLS spec recommends HelloVerify and Anti Replay protection be enabled,
  and these are enabled in the default mbedTLS config. Implement them here.

- To help compensate for the possible increase in code size, add a
  MICROPY_PY_SSL_DTLS build config macro that's enabled for EXTRA and
  above by default.

This allows bare metal mbedTLS ports to use DTLS with HelloVerify support.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-23 15:47:16 +10:00
Angus Gratton
41e0ec96cb extmod/mbedtls: Implement DTLS HelloVerify cookie support.
This is already enabled in the ESP-IDF mbedTLS config, so provide an
implementation of the cookie store functions. This allows DTLS connections
between two esp32 boards.

The session cookie store is a very simple dictionary associated with the
SSLContext. To work, the server needs to reuse the same SSLContext (but
cookies are never cleaned up, so a server with a high number of clients
should recycle the context periodically.)

Server code still needs to handle the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
error by waiting for the next UDP packet from the client.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-23 15:47:16 +10:00
Damien George
c6423d5d8e tests/multi_bluetooth: Synchronise MTU exchange in BLE MTU tests.
With the recent update to ESP-IDF 5.4.2, there is a change in BLE event
behaviour which makes `tests/multi_bluetooth/ble_mtu.py` and
`tests/multi_bluetooth/ble_mtu_peripheral.py` now fail on ESP32 with IDF
5.4.2.

The change in behaviour is that MTU_EXCHANGE events can now occur before
CENTRAL_CONNECT/PERIPHERAL_CONNECT events.  That seems a bit strange,
because the MTU exchange occurs after the connection.  And looking at the
timing of the events there is exactly 100ms between them, ie MTU_EXCHANGE
fires and then exactly 100ms later CENTRAL_CONNECT/PERIPHERAL_CONNECT
fires.

It's unknown if this is a bug in (Espressif's) NimBLE, a subtle change in
scheduling with still valid behaviour, an intended change, a change allowed
under the BLE spec, or something else.

But in order to move forward with updating to IDF 5.4.2, the relevant tests
have been adjusted so they can pass.  The test just needs to wait a bit
between doing the connect and doing the MTU exchange, so the other side
sees the original/correct ordering of events.  This wait is done using the
multitest synchronisation primitives (broadcast and wait).

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:53:28 +10:00
Damien George
10ef3e4ac2 esp32: Update to use ESP-IDF v5.4.2.
This is a patch release of the IDF.  Comparing with 5.4.1, firmware size is
up by about 1.5k on ESP32 and 9k on ESP32-S3.  But IRAM usage (of the IDF)
is down by about 500 byte on ESP32 and DRAM usage is down by about 20k on
ESP32 and 10k on ESP32-S3.

Testing on ESP32, ESP32-S2, ESP32-S3 and ESP32-C3 shows no regressions,
except in BLE MTU ordering (the MTU exchange event occuring before the
connect event).

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:52:49 +10:00
Damien George
1ab1f857b3 tests/extmod_hardware/machine_uart_irq_break.py: Remove send_uart.
This is no longer needed, the esp32 port can now pass this test using just
a single UART.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:51:10 +10:00
Damien George
79b2d4ff22 esp32/machine_uart: Improve sendbreak so it doesn't reconfig the UART.
Currently, `UART.sendbreak()` on esp32 will reconfigure the UART to a
slower baudrate and send out a null byte, to synthesise a break condition.
That's not great because it changes the baudrate of the RX path as well,
which could miss incoming bytes while sending the break.

This commit changes the sendbreak implementation to just reconfigure the TX
pin as GPIO in output mode, and hold the pin low for the required duration.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:50:29 +10:00
Damien George
941b7e35ac tests/run-tests.py: Use TEST_TIMEOUT as timeout for bare-metal tests.
This parameter is already used for PC-based tests (eg unix and webassembly
ports), and it makes sense for it to be used for bare-metal ports as well.
That way the timeout is configurable for all targets.

Because this increases the default timeout from 10s to 30s, this fixes some
long-running tests that would previously fail due to a timeout such as
`thread/stress_aes.py` on ESP32.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:42:44 +10:00
Damien George
cc774c3daf tools/pyboard.py: Add timeout argument to Pyboard.exec_/exec.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:42:44 +10:00
Damien George
b7e734bfb7 tests/net_inet: Update micropython.org certificate for SSL tests.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:40:45 +10:00
Damien George
8a457b8cf9 tools/ci.sh: Change averaging to 1 for run-perfbench.py test.
The `run-perfbench.py` test is run as part of CI, but the actual
performance results are not used.  Rather, the test is just testing that
all the performance tests run correctly.

So there's no need to run with the default averaging of 8 (which runs each
test 8 times and takes the average time for the performance result) which
can take a lot of time for slower builds, eg unix sanitize, settrace and
stackless builds.

This commit changes the averaging to just 1.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 12:39:42 +10:00
Damien George
677a0e0124 docs/reference/speed_python: Document schedule/GIL limitation of native.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:37:16 +10:00
Damien George
b070765427 tests/thread: Allow thread tests to pass with the native emitter.
The native emitter will not release/bounce the GIL when running code, so
if it runs tight loops then no other threads get a chance to run (if the
GIL is enabled).  So for the thread tests, explicitly include a call to
`time.sleep(0)` (or equivalent) to bounce the GIL and give other threads a
chance to run.

For some tests (eg `thread_coop.py`) the whole point of the test is to test
that the GIL is correctly bounced.  So for those cases force the use of the
bytecode emitter for the busy functions.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:37:00 +10:00
Damien George
b15065b95e github/workflows: Add new CI job to test unix port with GIL enabled.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:35:38 +10:00
Damien George
b6460df721 unix: Allow the GIL to be enabled.
The unix port can now be built with the GIL enabled, by passing
MICROPY_PY_THREAD_GIL=1 on the make command line.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:35:38 +10:00
Damien George
92193112bf tools/ci.sh: Skip thread/stress_recurse.py on unix qemu test runs.
This test passes sometimes and fails other times.  Eventually that should
be fixed, but for now just skip this test.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:10:11 +10:00
Damien George
279f51d7d2 tools/ci.sh: Skip thread/stress_heap.py test on macOS test run.
This test passes sometimes and fails other times.  Eventually that should
be fixed, but for now just skip this test.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:10:11 +10:00
Damien George
f835b1626d tools/ci.sh: Increase timeout for stackless clang test runs.
Stackless mode makes `tests/thread/stress_aes.py` slow, around 75 seconds
for this CI job (probably due to contention among the many threads for the
GC lock, to allocate frames for function calls).  So increase the timeout
to allow this test to pass.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:10:11 +10:00
Damien George
081213ec9d tools/ci.sh: Increase timeout for unix qemu test runs.
The qemu emulation introduces enough overhead that the
`tests/thread/stress_aes.py` test overruns the default timeout.  So
increase it to allow this test to pass.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:10:07 +10:00
Damien George
167c888df9 tests/run-tests.py: Detect threading and automatically run thread tests.
When detecting the target platform, also check if it has threading and
whether the GIL is enabled or not (using the new attribute
`sys.implementation._thread`).  If threading is available, add the thread
tests to the set of tests to run (unless the set of tests is explicitly
given).

With this change, the unix port no longer needs to explicitly run the set
of thread tests, so that line has been removed from the Makefile.

This change will make sure thread tests are run with other testing
combinations.  In particular, thread tests are now run:
- on the unix port with the native emitter
- on macOS builds
- on unix qemu, the architectures MIPS, ARM and RISCV-64

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:06:09 +10:00
Damien George
377924b443 tests/thread/stress_aes.py: Reduce test time on PC targets.
This thread stress test is quite intensive and can run for a long time on
certain targets.  For example, builds with stackless enabled are slower
than non-stackless, and this test in stackless mode takes around 2 minutes
on the unix port of MicroPython with the existing parameters of
`n_thread=20` and `n_loop=5`.

It's not really necessary to test 20 threads at once, that's not really
going to test anything more than 10 at once.  So reduce the parameters to
keep the running time reasonable.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-23 11:02:21 +10:00
Damien George
97fd18a7e2 tests/extmod/select_poll_eintr.py: Pre-allocate global variables.
This is a workaround for the case where threading is enabled without a GIL.
In such a configuration, creating a new global variable is not atomic and
threads have race conditions resizing/accessing the global dict.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-22 23:22:05 +10:00
Damien George
18f2e94846 py/modsys: Add sys.implementation._thread attribute.
This is useful to distinguish between GIL and non-GIL builds.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-22 23:22:05 +10:00
Alessandro Gatti
e993f53877 docs/develop/natmod: Add notes on Picolibc and natmods.
This commit adds some documentation on what are the limitations of using
Picolibc as a standard C library for native modules.

This also contains a reference to the "errno" issue when building
natmods on RV32 that the PR this commit is part of, as it is not obvious
how to approach this issue when encountered for the first time.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-20 23:03:40 +10:00
Alessandro Gatti
b63e528076 examples/natmod/btree: Fix build on RV32 with Picolibc.
This commit fixes building the "btree" example natmod on RV32 when
Picolibc is being used and uses thread-local storage for storing the
errno variable.

The fix is surprisingly simple: Picolibc allows overriding the function
that will provide a pointer to the "errno" variable, and the btree
natmod integration code already has all of this machinery set up as part
of its library integration.  Redirecting Picolibc to the already
existing pointer provider function via a compile-time definition is
enough to let the module compile and pass QEMU tests.

This workaround will work on any Picolibc versions (Arm, RV32, Xtensa,
etc.) even if TLS support was not enabled to begin with, and will
effectively do nothing if the toolchain used will rely on Newlib to
provide standard C library functions.

Given that the btree module now builds and passes the relevant natmod
tests, said module is now part of the QEMU port's natmod testing
procedure, and CI now will build the btree module for RV32 as part to
its checks.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-20 23:03:40 +10:00
Yanfeng Liu
5f55f8d01a tools/pyboard.py: Align execpty prefix.
This aligns the prefix string in L285 to that in L284 though the
two strings have equal length.

Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
2025-07-20 22:59:06 +10:00
Yanfeng Liu
a8d50fb653 py/mkrules.mk: Mute blobless errors.
This mutes usage error for blobless update from older `git` to
reduce noise upon submodule updating.

Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
2025-07-20 22:59:06 +10:00
Anson Mansfield
ddf2c3afb1 py/objcode: Remove co_lnotab from v2 preview.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-18 10:59:21 -04:00
Anson Mansfield
7b38fa4fa3 tests/basics/fun_code_lnotab: Test removal of co_lnotab from v2.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-18 10:59:21 -04:00
Angus Gratton
17fbc5abdc py/parsenum: Extend mp_parse_num_integer() to parse long long.
If big integer support is 'long long' then mp_parse_num_integer() can
parse to it directly instead of failing over from small int. This means
strtoll() is no longer pulled in, and fixes some bugs parsing long long
integers (i.e. can now parse negative values correctly, can now parse
values which aren't NULL terminated).

The (default) smallint parsing compiled code should stay the same here,
macros and a typedef are used to abstract some parts of it out.

When bigint is long long we parse to 'unsigned long long' first (to avoid
the code size hit of pulling in signed 64-bit math routines) and the
convert to signed at the end.

One tricky case this routine correctly overflows on is
int("9223372036854775808") which is one more than LLONG_MAX in decimal. No
unit test case added for this as it's too hard to detect 64-bit long
integer mode.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:12:16 +10:00
Angus Gratton
e9845ab20e py/smallint: Update mp_small_int_mul_overflow() to perform the multiply.
Makes it compatible with the __builtin_mul_overflow() syntax, used in
follow-up commit.

Includes optimisation in runtime.c to minimise the code size impact from
additional param.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:12:13 +10:00
Angus Gratton
516aa02104 py/objint_longlong: Add arithmetic overflow checks.
Long long big integer support now raises an exception on overflow rather
than returning an undefined result.

Also adds an error when shifting by a negative value.

The new arithmetic checks are added in the misc.h header.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:12:05 +10:00
Angus Gratton
d07f103d68 tests: Skip bm_pidigits perf test if no arbitrary precision int support.
The other performance tests run and pass with only 64-bit big integer
support.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:11:44 +10:00
Angus Gratton
0cf1e7c059 tests/thread: Rename thread_lock4 test to thread_lock4_intbig.
Relies on arbitrary precision math, so won't run on a port which
has threads & limited bigint support.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:11:34 +10:00
Angus Gratton
a54b5d9aed unix/variants: Add a 'longlong' variant to test 64-bit bigints in CI.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:11:08 +10:00
Angus Gratton
6d93b150b8 tests/extmod/json_loads_int_64.py: Add test cases for LONGINT parse.
These tests cover the use of mp_obj_new_int_from_str_len when
mp_parse_num_integer overflows the SMALLINT limit, and also the case where
the value may not be null terminated.

Placed in a separate test file so that extmod/json test doesn't rely on
bigint support.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:10:48 +10:00
Angus Gratton
2d8d64059f tests: Add specific tests for "long long" 64-bit bigints.
These will run on all ports which support them, but importantly
they'll also run on ports that don't support arbitrary precision
but do support 64-bit long ints.

Includes some test workarounds to account for things which will overflow
once "long long" big integers overflow (added in follow-up commit):

- uctypes_array_load_store test was failing already, now won't parse.
- all the ffi_int tests contain 64-bit unsigned values, that won't parse
  as long long.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:10:44 +10:00
webreflection
c72a3e528d webassembly/objpyproxy: Avoid throwing on implicit symbols access.
This commit improves get handling by guarding against implicit unknown
symbols accessed directly by specific JS native APIs.

Fixes issue #17657.

Signed-off-by: Andrea Giammarchi <andrea.giammarchi@gmail.com>
2025-07-17 14:37:53 +10:00
Anson Mansfield
554f114f18 examples/rp2/pio_uart_rx.py: Fix use of PIO constants.
Running the unmodified `pio_uart_rx.py` example by uploading the file and
importing it doesn't succeed, and instead emits a NameError at line 26.

Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-17 14:31:42 +10:00
Damien George
0b698b8241 rp2/mpnetworkport: Deregister all sys timeouts when netif is removed.
When mDNS is active on a netif it registers a lot of timeouts, namely:

    mdns_probe_and_announce
    mdns_handle_tc_question

    mdns_multicast_probe_timeout_reset_ipv4
    mdns_multicast_timeout_25ttl_reset_ipv4
    mdns_multicast_timeout_reset_ipv4
    mdns_send_multicast_msg_delayed_ipv4
    mdns_send_unicast_msg_delayed_ipv4

    mdns_multicast_probe_timeout_reset_ipv6
    mdns_multicast_timeout_25ttl_reset_ipv6
    mdns_multicast_timeout_reset_ipv6
    mdns_send_multicast_msg_delayed_ipv6
    mdns_send_unicast_msg_delayed_ipv6

These may still be active after a netif is removed, and if they are called
they will find that the mDNS state pointer in the netif is NULL and they
will crash.

These functions could be explicitly removed using `sys_untimeout()`, but
`mdns_handle_tc_question()` is static so it's not possible to access it.
Instead use the new `sys_untimeout_all_with_arg()` helper to deregister all
timeout callbacks when a netif is removed.

Fixes issue #17621.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-17 13:39:10 +10:00
Damien George
cf490ed346 extmod/network_lwip: Add sys_untimeout_all_with_arg helper function.
Really lwIP should provide this, to deregister all callbacks on the given
netif.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-17 13:38:58 +10:00
Damien George
8504391766 alif/lwip_inc: Refactor lwipopts.h to use extmod's common options.
This change is a no-op for the firmware.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-17 13:28:24 +10:00
Jeff Epler
628d53d23c unix/coverage: Expand mp_printf coverage tests.
Test 'l' and 'll' sized objects.  When the platform's `mp_int_t` is not 64
bits, dummy values are printed instead so the test result can match across
all platforms.

Ensure hex test values have a letter so 'x' vs 'X' is tested.

And test 'p' and 'P' pointer printing.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-16 11:13:08 +10:00
Jeff Epler
0a4f9ec46b py/mpprint: Rework integer vararg handling.
This adds support for %llx (needed by XINT_FMT for printing cell objects)
and incidentally support for capitalized output of %P.

It also reduces code size due to the common handling of all integers.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-16 11:12:31 +10:00
Jim Mussared
5e9189d6d1 py/vm: Avoid heap-allocating slices when subscripting built-ins.
This commit adds a fast-path optimisation for when a BUILD_SLICE is
immediately followed by a LOAD/STORE_SUBSCR for a native type, to avoid
needing to allocate the slice on the heap.

In some cases (e.g. `a[1:3] = x`) this can result in no allocations at all.

We can't do this for instance types because the get/set/delattr
implementation may keep a reference to the slice.

Adds more tests to the basic slice tests to ensure that a stack-allocated
slice never makes it to Python, and also a heapalloc test that verifies
(when using bytecode) that assigning to a slice is no-alloc.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
2025-07-16 00:12:47 +10:00
Yanfeng Liu
aa2362d4de unix/Makefile: Drop include path of "i686-linux-gnu".
This drops use of non-existing path `/usr/include/i686-linux-gnu` as
default include paths shall suffice.

Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
2025-07-15 14:03:06 +10:00
Yanfeng Liu
274306860b tests/extmod: Close UDP sockets at end of test.
This adds call to release UDP port in a timely manner, so they can be
reused in subsequent tests.  Otherwise, one could face issue like #17623.

Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
2025-07-15 13:57:21 +10:00
Damien George
8f8f853982 tests/run-tests.py: Consider tests ending in _async.py as async tests.
The test `micropython/ringio_async.py` is a test that requires async
keyword support, and will fail with SyntaxError on targets that don't
support async/await.  Really it should be skipped on such targets, and this
commit makes sure that's the case.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-12 23:48:17 +10:00
Damien George
125d19ce7b tests/micropython: Add missing SystemExit after printing SKIP.
The test runner expects `print("SKIP")` to be followed by
`raise SystemExit`.  Otherwise it waits for 10 seconds for the target to
do a soft reset before timing out and continuing.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-12 23:32:28 +10:00
Damien George
908f938c44 tests/extmod/asyncio_iterator_event.py: Use format instead of f-string.
Some targets don't have f-strings enabled, so try not to use them in tests.
Rather, use `str.format`, which is more portable.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-12 22:37:56 +10:00
Jeff Epler
499bedf7aa tools/ci.sh: Always call apt-get update before apt-get install.
There have been recent build failures in build_renesas_ra_board.  It
appears to be the case that a security update for this package was recently
issued by Ubuntu for CVE-2025-4565 and the buggy version is no longer on
package servers.  However, it is still referred to by the cached apt
metadata in the GitHub runners.

Add `apt-get update` to fix this, and audit for other sites in `ci.sh`
where it might also be necessary.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-12 22:13:29 +10:00
Yoctopuce dev
df05caea6c shared/timeutils: Standardize supported date range on all platforms.
This is code makes sure that time functions work properly on a
reasonable date range, on all platforms, regardless of the epoch.
The suggested minimum range is 1970 to 2099.

In order to reduce code footprint, code to support far away dates
is only enabled specified by the port.

New types are defined to identify timestamps.

The implementation with the smallest code footprint is when
support timerange is limited to 1970-2099 and Epoch is 1970.
This makes it possible to use 32 bit unsigned integers for
all timestamps.

On ARM4F, adding support for dates up to year 3000 adds
460 bytes of code. Supporting dates back to 1600 adds
another 44 bytes of code.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-07-09 11:54:21 +10:00
Yoctopuce dev
c4a88f2ce7 py/obj: Add functions to retrieve large integers from mp_obj_t.
This commit provides helpers to retrieve integer values from
mp_obj_t when the content does not fit in a 32 bits integer,
without risking an implicit wrap due to an int overflow.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-07-09 11:54:21 +10:00
Anson Mansfield
49159ef6b7 py/objcode: Implement co_lines method.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-08 11:03:22 -04:00
Anson Mansfield
4b6d1085d1 tests/basics/fun_code_colines: Test decoded co_lines values.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-08 11:03:22 -04:00
Anson Mansfield
d6b62a28fe tests/basics/fun_code_full: Test code objects with full feature set.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-08 11:03:22 -04:00
Anson Mansfield
0732c45683 py/showbc: Use line-number decoding helper.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-08 11:03:22 -04:00
Anson Mansfield
00fe312f83 py/bc: Factor out helper for line-number decoding.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-07-08 11:03:22 -04:00
Damien George
05342b013d tools/mpremote: Support OSError's on targets without errno.
Targets without the `errno` module enabled will not render `OSError`s
with the name of the error.  Instead they just print the numeric error
code.

Add support for such targets by explicitly recognising certain error codes.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 21:52:56 +10:00
Jeff Epler
da3709a738 unix/coverage: Add missing MP_OBJ_FROM_PTR casts.
An attempt to build the coverage module into the nanbox binary failed, but
pointed out that these sites needed explicit conversion from pointer to
object.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-08 21:50:27 +10:00
Damien George
99740dbace stm32/stm32.mk: Error out if compiling for cortex-m55 on old gcc.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:28:58 +10:00
Damien George
50ea398b00 stm32/boards/NUCLEO_N657X0: Add new board definition files.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:28:58 +10:00
Damien George
3189e49d28 stm32/boards/OPENMV_N6: Add new board definition files.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:28:58 +10:00
Damien George
7016900fbe stm32/spi: Fail spi_init if pins can't be configured.
Follows the UART and I2C drivers.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:25:14 +10:00
Damien George
acb294f61a stm32/mboot: Add support for STM32N6xx MCUs.
Works in the usual USB DFU mode, and can program external SPI flash.  It
will enable XSPI memory-mapped mode before jumping to the application
firmware in the external SPI flash.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:25:14 +10:00
Damien George
96b8f3aebc stm32/boards: Add board support files for N6.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:25:14 +10:00
Damien George
959e910366 stm32/lwip_inc: Increase lwIP memory on N6.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:25:14 +10:00
iabdalkader
eaed2518fa stm32/main: Disable D-cache when debugging N6.
See ST Errata ES0620 - Rev 0.2 section 2.1.2.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-07-08 16:25:10 +10:00
Damien George
eb3ea9ee13 stm32: Add support for STM32N6xx MCUs.
This commit adds preliminary support for ST's new STM32N6xx MCUs.

Supported features of this MCU so far are:
- basic clock tree initialisation, running at 800MHz
- fully working USB
- XSPI in memory-mapped mode
- machine.Pin
- machine.UART
- RTC and deepsleep support
- SD card
- filesystem
- ROMFS
- WiFi and BLE via cyw43-driver (SDIO backend)

Note that the N6 does not have internal flash, and has some tricky boot
sequence, so using a custom bootloader (mboot) is almost a necessity.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:24:27 +10:00
Damien George
24fd5f7268 stm32/boards/make-pins.py: Support up to GPIO-O.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:24:27 +10:00
Damien George
228abf8fc7 lib/stm32lib: Update library for N6 v1.1.0.
Changes in this new library version are:
- Add N6 HAL at v1.1.0.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:24:27 +10:00
Damien George
d8f004b62f lib/libm_dbl: Support FLT_EVAL_METHOD == 16.
That's almost the same as FLT_EVAL_METHOD == 0, but indicates the
presence of _Float16_t support.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:24:27 +10:00
Damien George
62a674c9c4 drivers: Support special QSPI direct-read protocol.
This is useful for interfaces that stay in memory-mapped mode by default.
They can implement this method with a simple `memcpy()`.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 16:24:27 +10:00
Yuuki NAGAO
eaffbacb10 stm32/machine_adc: Add machine.ADC implementation for STM32L1.
Signed-off-by: Yuuki NAGAO <wf.yn386@gmail.com>
2025-07-08 14:01:41 +10:00
Matt Trentini
42cfa7cdae stm32/dma: Extend STM32H5 DMA use to SPI3 and SPI4.
Attempting to configure SPI3 and SPI4 for the STM32H5 would fail with a
linker error.  This patch resolves that, ensuring that appropriate DMA
channels are assigned to those SPI resources.

Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2025-07-08 13:57:58 +10:00
Yuuki NAGAO
f3c56c81ea stm32/irq: Change SPI IRQ priority to be higher than DMA IRQ.
On STM32H5/STM32H7, SPI flash cannot use as storage device with DMA.  SPI
interruption may not be genearated even if DMA transfer has been done.
This is due to lower priority of SPI interruption than DMA.

This commit changes SPI interrupt priority more higher than DMA's priority.

Signed-off-by: Yuuki NAGAO <wf.yn386@gmail.com>
2025-07-08 13:52:22 +10:00
Damien George
168e2c8f66 tests/extmod/select_poll_eintr.py: Skip test if target can't bind.
Eg on PYBV10 with THREAD variant, the firmware has both the `_thread` and
`socket` modules but no NIC.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:19:00 +10:00
Damien George
b680011d91 tests/ports/stm32: Tweak tests to run on a wider set of boards.
There should be no change to these tests for existing PYBV1x and PYBD_SFx
boards.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:18:55 +10:00
Damien George
29b5c2207c tests/extmod_hardware/machine_uart_irq_rxidle.py: Test multiple writes.
This tests that the RXIDLE callback is called correctly after a second lot
of bytes are received.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:18:13 +10:00
Damien George
a4a098ff82 tests/extmod_hardware/machine_uart_irq_rxidle.py: Ignore inital IRQ.
On stm32, the hardware generates an RXIDLE IRQ after enabling the UART,
because the RX line is technically idle.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:18:09 +10:00
Damien George
a2e3055d2d tests/extmod_hardware: Add UART config for STM32WB boards.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:18:05 +10:00
Damien George
bb484b6d81 tests/extmod/machine_uart_tx.py: Support STM32WB boards.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:17:57 +10:00
Damien George
0975255f86 stm32/uart: Suppress additional RX idle IRQs on F4/L1.
These MCUs only clear the RX idle IRQ if the data register is read, which
won't occur if the only IRQ is the RX idle IRQ (because then reading and
discarding the DR may lead to lost data).

To work around this, explicitly suppress the RX idle IRQ so that it's only
passed through to the Python callback once.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:15:47 +10:00
Damien George
d5246cea61 stm32/machine_adc: Fix internal ADC channel reading on WB MCUs.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:15:39 +10:00
Damien George
c9adabc25a stm32/adc: Fix core temperature reading on WB55.
It needs a divisor of 100 because the calibration temperatures are 30 and
130 degrees, similar to the H5.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:15:35 +10:00
Damien George
841439d5fb stm32/adc: Simplify ADC calibration settings.
Combine the common settings for L1/L4/WB with existing G0/G4/H5 settings.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:14:48 +10:00
Damien George
ea2000b81d stm32/adc: Apply re-read errata for WB55.
Following 17898f8607.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 13:14:43 +10:00
Damien George
9a9e5529af zephyr/machine_pin: Retry configuring gpio with just GPIO_OUTPUT.
Some targets like frdm_k64f don't support GPIO_OUTPUT|GPIO_INPUT, so just
use GPIO_OUTPUT in those cases (it seems they still support reading the
current output state even when configured only as GPIO_OUTPUT, unlike other
targets which require both settings).

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
bf432a3e0f zephyr/machine_timer: Make machine.Timer id argument optional.
With a default of -1, for soft timer.  This matches other ports, and the
`extmod/machine_timer.c` implementation.

This change allows the `tests/extmod/machine_soft_timer.py` test to pass.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
0fd65c44cf zephyr/mpconfigport: Enable emergency exception buffer.
Needed to pass exception tests.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
6881618307 zephyr/mpconfigport: Enable sys.maxsize.
Costs +48 bytes.  Useful to introspect the target.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
ec65cac971 zephyr/boards/rpi_pico: Add board configuration for rpi_pico.
Although the rpi_pico can already build and run with the zephyr port, this
configuration improves it in a number of ways:
- Use the USB CDC ACM as the REPL, rather than just a UART.
- Enable I2C and SPI, and add I2C1.
- Enable a filesystem, which matches exactly the rp2 port's RPI_PICO
  configuration.  So switching between zephyr and rp2 is possible and will
  retain the filesystem.
- Make the MicroPython GC heap make the most use of the available RAM.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
0faddb3c8a zephyr/boards/nucleo_wb55rg: Enable BLE, I2C, SPI and add filesystem.
Bluetooth works well now on this board, so enable all supported features.

Also increase the MicroPython GC heap size to make use of the available
RAM.

Unfortunately the filesystem does not match the stm32 port's NUCLEO_WB55
configuration.  That's not possible to do because stm32 uses a 512 byte
flash erase size, while zephyr uses 4096 bytes.  But at least here in
zephyr there's now a sizable and usable filesystem.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
35880d432a zephyr/boards/frdm_k64f: Improve board configuration.
Changes:
- Enable CONFIG_PWM so that `machine.PWM()` works.
- Increase MicroPython GC heap size.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
d0ccaff5b7 zephyr/mpconfigport: Enable MICROPY_NLR_THUMB_USE_LONG_JUMP.
Needed for some ARMv6M boards, eg rpi_pico.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
07285323cf zephyr/mpconfigport: Enable import of mpy and a few related features.
Support for importing .mpy files is quite fundamental to MicroPython these
days, eg it allows installing more efficient .mpy code via "mip install"
(and installing `unittest` only works with the .mpy version because the .py
version uses f-strings, which are not enabled on the zephyr port).  So
enable it generally for use by all boards.

As part of this, also enable:
- min/max: needed by `micropython/import_mpy_invalid.py`, and widely used
- sys.modules: needed by `run-tests.py` to run .mpy tests with --via-mpy
- io module: needed to run .mpy tests, and useful for `io.IOBase`
- array slice assign: needed to run .mpy tests, and generally useful as a
  way to do a memory copy.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
16b00cd6e7 zephyr/mpconfigport: Enable machine.SoftI2C and machine.SoftSPI.
These work now that the C-level pin HAL is implemented.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
19814bf50f zephyr/mphalport: Implement C-level pin HAL.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 11:15:11 +10:00
Damien George
359887933c zephyr/machine_pin: Allow constructing a Pin with an existing Pin.
Following other ports.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 10:10:34 +10:00
Damien George
9b97a30943 zephyr/machine_pin: Add Pin.OPEN_DRAIN constant.
Adding this constant is all that's needed to support open-drain pins.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 10:10:33 +10:00
Damien George
6fd069e8a5 zephyr/src: Fix USB device_next driver to work with zephyr 4.0.0.
The blocklist argument is not available in zephyr 4.0.0.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 10:10:16 +10:00
Damien George
6a53319336 zephyr/src: Increase UART input buffer to 512 bytes and reduce latency.
There are two changes here:

1. Increase the UART input bufffer to 512 bytes.  That's necessary to get
   basic REPL reliability tests working, and helps improve `mpremote`
   usage, eg copying large files.

2. Remove `uart_sem` semaphore.  This is no longer needed because
   `zephyr_getchar()` should be fully non-blocking and have as low a
   latency as possible.  `mp_hal_stdin_rx_chr()` (which calls
   `zephyr_getchar`) already uses `MICROPY_EVENT_POLL_HOOK` to get
   an efficient wait, and doing an extra wait and check for the
   semaphore in `zephyr_getchar()` just introduces unnecessary latency and
   can lead to slower input, and potentially overflowing the UART input
   buffer.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 10:10:16 +10:00
Damien George
4951a06bbb zephyr: Enable sys.stdin/out/err.
This change enables `sys.stdin`, `sys.stdout` and `sys.stderr` objects.
They are useful for general IO, and also help with testing zephyr boards.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 10:10:16 +10:00
Damien George
6b82eb75be zephyr/main: Add /flash/lib or /sd/lib to sys.path on start up.
If there is a filesystem available, this change makes sure there is a "lib"
in `sys.path`, eg so that "mip install" works correctly.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 10:10:16 +10:00
Damien George
d9b4327c66 zephyr/main: Execute boot.py and main.py like other ports.
Changes here make the zephyr port act the same as other ports for the
start up and shut down sequence:
- `boot.py` is executed if it exists, and can force a soft reset
- `main.py` is only executed if in friendly REPL and if `boot.py` executed
  successfully; and it can also force a soft reset
- print "MPY: " before "soft reboot" on soft reset

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 10:10:16 +10:00
David Schneider
16d9e704ae zephyr: Update generated header path.
Support disabled LEGACY_GENERATED_INCLUDE_PATH compatibility option.
Since Zephyr 3.7 generated include files are namespaced.

See also: zephyrproject-rtos/zephyr@bbe5e1e6eb

Signed-off-by: David Schneider <schneidav81@gmail.com>
2025-07-08 09:53:24 +10:00
Damien George
5eb94df09e zephyr/prj.conf: Use UART for console as default, not CONSOLE_SUBSYS.
Most boards enable the UART console because it's needed for USB (where USB
CDC creates a virtual UART), and for ctrl-C to work.

The `prj_minimal.conf` settings still use CONSOLE_SUBSYS.

Fixes issue #17608.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 09:29:30 +10:00
Damien George
5321b666ea zephyr/README: Update URL describing QEMU network settings.
Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 09:29:30 +10:00
Damien George
9171865782 zephyr/boards: Disable WDT on qemu boards and networking for cortex_m3.
This gets qemu_x86 and qemu_cortex_m3 building with `prj.conf` settings.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 09:29:30 +10:00
Damien George
49dbe1e272 zephyr/machine_pin: Configure OUT pin also as input so it's readable.
Zephyr allows setting both GPIO_OUTPUT and GPIO_INPUT on a pin, which means
it's an output pin that can have its current value read.

Fixes issue #17596.

Signed-off-by: Damien George <damien@micropython.org>
2025-07-08 08:57:48 +10:00
Daniel Campora
abcf023554 zephyr/machine_uart: Complete UART driver and make it interrupt driven.
Before this commit the UART would only work in very simple use cases.
Receiving large amounts of data would result in lost bytes.  Plus the print
function would crash due to `uart_config_get()` returning incorrect values.
Additionally, receiving data with `timeout==0` would fail even if data was
already available in the internal UART Rx FIFO.

This commit fixes those issues.  The non-implemented functions have also
been made usable.

Signed-off-by: Daniel Campora <danicampora@gmail.com>
2025-07-08 07:50:06 +10:00
Daniël van de Giessen
431b79146e esp32/panichandler: Support building against IDFv5.4.2.
The IDF panic handler resets the watchdog timeout to prevent the printing
of the error message from being cut off by a WDT reset.  We use the exact
same function call in our wrapper function for the same purpose.

In IDFv5.4.2 the function used for this was changed from
`esp_panic_handler_reconfigure_wdts` to `esp_panic_handler_feed_wdts`,
specifically in this commit:
cd887ef59a

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-07-06 00:14:10 +10:00
Jeff Epler
a9801f9960 github/workflows: Use Python 3.11 for unix coverage testing.
This removes the need for an explicit `sys_settrace_features.py.exp` file.

This means that people testing locally will also need to install Python
3.11 in some way, such as with pyenv or uv, and use it during
`make VARIANT=coverage test`, or they will get failures.

When using Python from GitHub actions/setup-python, pip3 can't be wrapped
by sudo, because this invokes the operating system python instead.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:08:54 +10:00
Jeff Epler
a8c2b917e2 tools/ci.sh: Increase test timeout to 60s in coverage jobs.
The additional overhead of the settrace profiler means that the
`aes_stress.py` test was running too slowly on GitHub CI.  Double the
timeout to 60 seconds.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:08:13 +10:00
Jeff Epler
e415d03e7f github/workflows: Remove the unix "settrace" CI job.
This becomes redundant when the main coverage build includes settrace.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:07:14 +10:00
Jeff Epler
db0a836fc1 py/profile: Fix printing lineno in frame objects.
The argument corresponding to a `%q` specifier must be of type `qstr`, not
a narrower type like `int16_t`.  Not ensuring this caused an assertion
error on one Windows x64 build.

The argument corresponding to a `%d` specifier must be of type `int`, not a
potentially-wider type like `mp_uint_t`.  Not ensuring this prevented the
function name from being printed on the unix nanbox build.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:06:34 +10:00
Jeff Epler
f33f1aa9d3 unix/coverage: Initialize more code_state fields.
When `MICROPY_PY_SYS_SETTRACE` was enabled, a crash was seen in the
qemu_mips build.  It seems likely that this was due to these added fields
not being initialized.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:06:14 +10:00
Jeff Epler
f04475afd8 py/runtime: Initialize profile fields in mp_thread_init_state.
If the fields added for `MICROPY_PY_SYS_SETTRACE` are not initialized
properly, their value in a thread is indeterminate.  In particular, if the
callback is not NULL, it will be invoked as a function.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:05:47 +10:00
Jeff Epler
ff8c4e5943 tests/misc: Improve test coverage of py/profile.c.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:05:36 +10:00
Jeff Epler
fcfed6a0ea unix/variants/coverage: Enable sys.settrace.
The unix coverage variant should have all features enabled, so they can be
tested for coverage.  Therefore, enabled `MICROPY_PY_SYS_SETTRACE`.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-06 00:04:18 +10:00
Alessandro Gatti
2ab06b61b3 py/emitnative: Let emitters know the compiled entity's name.
This commit introduces an optional feature to provide to native emitters
the fully qualified name of the entity they are compiling.

This is achieved by altering the generic ASM API to provide a third
argument to the entry function, containing the name of the entity being
compiled.  Currently only the debug emitter uses this feature, as it is
not really useful for other emitters for the time being; in fact the
macros in question just strip the name away.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-04 16:07:04 +10:00
Andrew Leech
3a97175f5f tools/mpremote: Fix disconnect handling on Windows and Linux.
Changes in this commit:
- Handle SerialException on Windows when device disconnects.
- Print clean 'device disconnected' message instead of stack trace.
- Fix terminal formatting issues on Linux after disconnect.
- Return disconnected state after console cleanup to avoid terminal issues.

This ensures proper disconnect messages on both platforms without showing
confusing error traces to users.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-07-04 15:51:47 +10:00
Andrea Giammarchi
e33a0f4682 webassembly/objpyproxy: Avoid throwing on symbol or iterator has-check.
JavaScript code uses "Symbol in object" to brand check its own proxies, and
such checks should also work on the Python side.

Signed-off-by: Andrea Giammarchi <andrea.giammarchi@gmail.com>
2025-07-04 15:08:03 +10:00
iabdalkader
16f9d7fdc3 alif/machine_spi: Improve transfer function to poll events.
Poll events during SPI transfer (USB fails during long transfers
otherwise).  And add a timeout for the blocking transfer.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-07-03 21:43:10 +10:00
iabdalkader
4a1edc4866 alif/machine_pin: Add support for machine.Pin IRQ.
Matches existing `Pin.irq()` API.  Both rising and falling edge work.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-07-03 21:26:27 +10:00
Alessandro Gatti
1b0cdc0794 py/asmthumb: Clean up integer-indexed load/store emitters.
This commit cleans up the single entry point integer-indexed load/store
emitters that have been built by merging the single operand type
load/store functions in 1f5ba6998b.

To follow the same convention found in RV32 and Xtensa emitters, the
function operand size is not named after the left shift amount to apply
to the initial offset to get its true byte offset, but by a generic
"operand size".

Also, those functions were updated to use the new MP_FIT_UNSIGNED macros
to perform bit width checks when figuring out which opcode encoding is
the best one to use.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:43:17 +10:00
Alessandro Gatti
6fd7422a8e tests/run-tests.py: Allow injected code customisation.
This commit introduces a mechanism to customise the code that is
injected to the board when performing a test file upload and execution.

A new argument, --begin", is added so regular Python code can be
inserted in the injected fragment between the module file creation and
the effective file import.  This is needed for running larger tests
(usually ones that have been pre-compiled with
"--via-mpy --emit native") on ESP8266, as that board does not have
enough memory to fit certain blocks of code unless additional
configuration is performed.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:43:17 +10:00
Alessandro Gatti
0d435959e0 tests/micropython: Improve viper ptr boundary tests.
This commit reworks the Viper pointer boundary tests in order to make
them more accurate and easier to extend.

The tests are now easier to reason about in their output, using easier
to read values, and bit thresholds are now more configurable.  If a new
conditional code sequence is introduced, adding a new bit threshold is
just a matter of adding a value into a tuple at the beginning of the
relevant test file.

Load tests have also been made more accurate, with better function
templates to test register-indexed operations.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:43:02 +10:00
Alessandro Gatti
c8c8b04569 py/asmx64: Implement the full set of Viper load/store operations.
This commit expands the implementation of Viper load/store operations
that are optimised for the x86 platform.

Like x86, x64 already implemented all necessary functions and all it
took to expose these to Viper after the infrastructure refactoring
was to add a few defines.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:34:29 +10:00
Alessandro Gatti
a8dd393eee py/asmx86: Implement the full set of Viper load/store operations.
This commit expands the implementation of Viper load/store operations
that are optimised for the x86 platform.

Unlike other platforms, x86 already implemented all necessary
functions and all it took to expose these to Viper after the
infrastructure refactoring was to add a few defines.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:34:29 +10:00
Alessandro Gatti
7bb5f2da9d py/asmthumb: Remove redundant load/store opcode implementations.
This commit removes load/store opcode implementations that have been
made redundant in 1f5ba6998b.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:34:29 +10:00
Alessandro Gatti
12f36cc13c py/asmxtensa: Implement the full set of Viper load/store operations.
This commit expands the implementation of Viper load/store operations
that are optimised for the Xtensa platform.

Now both load and store emitters should generate the shortest possible
sequence in all cases.  Redundant specialised operation emitters have
been aliased to the general case implementation - this was the case of
integer-indexed load/store operations with a fixed offset of zero.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:34:29 +10:00
Alessandro Gatti
cd1b921bf2 py/asmarm: Implement the full set of Viper load/store operations.
This commit expands the implementation of Viper load/store operations
that are optimised for the Arm platform.

Now both load and store emitters should generate the shortest possible
sequence in all cases.  Redundant specialised operation emitters have
been folded into the general case implementation - this was the case of
integer-indexed load/store operations with a fixed offset of zero.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:34:29 +10:00
Alessandro Gatti
a8e0369826 py/asmrv32: Implement the full set of Viper load/store operations.
This commit expands the implementation of Viper load/store operations
that are optimised for the RV32 platform.

Given the way opcodes are encoded, all value sizes are implemented with
only two functions - one for loads and one for stores.  This should
reduce duplication with existing operations and should, in theory, save
space as some code is removed.  Both load and store emitters will
generate the shortest possible sequence (as long as the stack pointer is
not involved), using compressed opcodes when possible.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:34:29 +10:00
Alessandro Gatti
703d5acbad py/misc: Introduce macros to check values' bits size.
This commit adds two macros that lets check whether a given value can
fit an arbitrary number of bits, either as a signed or as an unsigned
number.

The native emitter code backends perform a lot of bit size checks to see
if a particular code sequence can be emitted instead of a generic one,
and each platform backend has its own ad-hoc macros (usually one per bit
count and signedness).

With these macros there's a single way to perform those checks, plus
there's no more chance for off-by-one mask length errors when dealing
with signed numbers.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-07-01 15:34:29 +10:00
Jeff Epler
1eb27e11f3 unix/README: Add some small documentation about sanitizers.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-01 15:19:07 +10:00
Jeff Epler
07c3bf21f2 tools/ci.sh: Disable "stack use after return" in ASan build.
This check, runtime-enabled by default in gcc 13 (and existing at least
since gcc 12, but runtime-disabled) changes the stack layout in ways that
are not compatible with assumptions spread across the core code (nlr, gc,
and stack checking).

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-01 15:18:29 +10:00
Jeff Epler
9a5cf0e3db github/workflows: Run the address sanitizer (ASan) build during CI.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-07-01 15:18:21 +10:00
Damien George
4bd99260dc alif/Makefile: Allow specifying a custom build directory.
Signed-off-by: Damien George <damien@micropython.org>
2025-06-26 14:22:13 +10:00
iabdalkader
9b38cf9f82 alif/README: Update README with build instructions.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-06-26 13:28:18 +10:00
iabdalkader
8cd8e146a4 alif/boards/ALIF_ENSEMBLE: Add board.json and deploy instructions.
The firmware for this board will now be built and available automatically.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-06-26 13:25:40 +10:00
Damien George
77c454829f tools/autobuild: Build alif boards as part of auto-build.
Signed-off-by: Damien George <damien@micropython.org>
2025-06-26 13:25:37 +10:00
Damien George
74a4cce6d1 alif/Makefile: Create firmware.zip with files needed for deploying.
The resulting `firmware.zip` file is self contained with everything needed
to deploy the firmware, eg over SE UART.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-26 13:25:02 +10:00
Andrew Leech
2f04381aeb extmod/modlwip: Fix crash when calling recv on listening socket.
Add check to prevent calling recv on a socket in the listening state.  This
prevents a crash/hard fault when user code mistakenly tries to recv on the
listening socket instead of on the accepted connection.

Add corresponding test case to demonstrate the bug.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-26 12:46:45 +10:00
ennyKey
2a46759fe8 stm32/uart: Enable UART FIFO for H7 MCUs.
The H7 has a hardware UART FIFO, so it's worth enabling it, to reduce the
chance of missed incoming characters.  Note that `HAL_UART_Init(&huart)`
does not activate the FIFO, it must be done explicitly by calling
`HAL_UARTEx_EnableFifoMode(&huart)`.

Signed-off-by: ennyKey <ennyKey@fn.de>
2025-06-26 12:36:04 +10:00
iabdalkader
5c6da11799 stm32/boards/ARDUINO_GIGA: Define additional GC blocks in SDRAM.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-06-26 12:10:04 +10:00
iabdalkader
cbe50635e8 stm32/main: Add support for additional GC blocks.
Add support for defining additional GC blocks via linker scripts.  A board
would need to define `_gc_blocks_table_start` and `_gc_blocks_table_end`
and within that region have pairs of (address, length) for each GC block
to add.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-06-26 12:10:04 +10:00
iabdalkader
0815b45479 stm32/boards/ARDUINO_PORTENTA_H7: Free reserved timer.
This pin is used for the camera clock on Portenta carrier, and vision
shield but it doesn't need to be reserved.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-06-26 10:49:51 +10:00
Garatronic
b4b7c0a003 esp32/boards/GARATRONIC_PYBSTICK26_ESP32C3: Add pybstick26-esp32c3 defn. 2025-06-26 10:44:48 +10:00
Damien George
6fee099cae py/misc: Fix fallback implementation of mp_popcount.
Tested using gcc 7.3.1 which does not have the popcount built-in and uses
this fallback version.  Without the fix, mpy-cross produces mpy files with
corrupt RISC-V machine code.  With the fix, mpy-cross output is correct.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-25 11:36:28 +10:00
Yoctopuce dev
e57aa7e70a py/obj: Fix nan handling in object REPR_C and REPR_D.
CPython math.nan is positive with regards to copysign.  The signaling bit
(aka sign flag) was incorrectly set.

In addition, REPR_C and REPR_D should only use the _true_ nan to prevent
system crash in case of hand-crafted floats.  For instance, with REPR_C,
any nan-like float following the pattern
`01111111 1xxxxxxx xxxxxxxx xxxxx1xx` would be switched to an immediate
object or a qstr string.  When the qstr index is too large, this would
cause a crash.

This commit fixes the issue, and adds the relevant test cases.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-06-24 00:30:08 +10:00
Yoctopuce dev
66c0148022 py/runtime: Add support for using __all__ in star import.
When the symbol `__all__` is defined in a module, `mp_import_all()` should
import all listed symbols into the global environment, rather than relying
on the underscore-is-private default.  This is the standard in CPython.

Each item is loaded in the same way as if it would be an explicit import
statement, and will invoke the module's `__getattr__` function if needed.
This provides a straightforward solution for fixing star import of modules
using a dynamic loader, such as `extmod/asyncio` (see issue #7266).

This improvement has been enabled at BASIC_FEATURES level, to avoid
impacting devices with limited ressources, for which star import is of
little use anyway.

Additionally, detailled reporting of errors during `__all__` import has
been implemented to match CPython, but this is only enabled when
ERROR_REPORTING is set to MICROPY_ERROR_REPORTING_DETAILED.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-06-23 16:05:12 +10:00
Ayush Singh
35f15cfdf2 zephyr/boards/beagleconnect_freedom: Remove board overlay.
Since MicroPython supports Zephyr v4.0.0, no need for overlay to enable
PWM.  It is enabled by default for a while now.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2025-06-23 11:39:43 +10:00
Ayush Singh
41fc3e1505 zephyr/boards/beagleconnect_freedom: Enable networking.
Having both PWM and networking enabled now works fine. So enable subg
networking.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2025-06-23 11:39:21 +10:00
robert-hh
32e69f7fdb samd/boards: Change the SparkFun vendor name to SparkFun.
Only the board.json files are affected. No other file uses the
style "Sparkfun". The documentation is fine.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-06-19 15:12:49 +02:00
Andrew Leech
09541b7896 py/repl: Skip private variables when printing tab completion options.
Any '_' variables/functions in frozen modules are currently printed, when
they shouldn't be.  That's due to underscore names possibly existing
between the start and end qstrs which are used to print the auto-complete
matches.  The underscore names should be skipped when iterating between the
two boundary qstrs.

The underscore attributes are removed from the extra coverage exp file
because tab completing "import <tab>" no longer lists modules beginning
with an underscore.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-19 17:23:42 +10:00
Andrew Leech
8eb5636996 tests/cmdline: Add a test for REPL paste mode.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-19 17:23:42 +10:00
Andrew Leech
5e965618be tests/run-tests.py: Add support for ctrl keys in REPL tests.
This allows having {\xDD} in tests, which will be expanded to the given
hex character.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-19 17:23:39 +10:00
Phil Howard
c16a4db151 rp2/CMakeLists.txt: Make linker script configurable.
Add `MICROPY_BOARD_LINKER_SCRIPT` to specify a custom linker script for rp2
boards/variants.

This may, for example, include a PSRAM region so that C buffers or
otherwise can be allocated into PSRAM.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-06-19 11:00:10 +10:00
Phil Howard
1a060e87cd rp2/CMakeLists.txt: Make board's pins.csv configurable.
Allow `mpconfigboard.cmake` to specify a custom `MICROPY_BOARD_PINS` to
override `${MICROPY_BOARD_DIR}/pins.csv`.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-06-19 10:47:50 +10:00
Phil Howard
dc8daad3c9 rp2/rp2_flash: Add default MICROPY_HW_FLASH_MAX_FREQ.
Set a default MICROPY_HW_FLASH_MAX_FREQ if PICO_FLASH_SPI_CLKDIV
is unset.

Use a divider of 4, which is the default in boot2_generic_03h.S.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-06-17 15:17:12 +01:00
Phil Howard
b725c26b4e rp2/rp2_flash: Add MICROPY_HW_FLASH_MAX_FREQ to replace fixed max freq.
Assuming a 133MHz capable flash in 91cff8e4f1
caused `rp2_flash_set_timing_internal` to set out of range dividers for
some boards (anything with value of 4 and flash that doesn't tolerate
higher speeds).

This affected (at least) the XIAO RP2350 board, making it non-bootable.

Since Pico SDK's `PICO_FLASH_SPI_CLKDIV` is entirely unreliable on a system
with a variable system clock (users can change it at runtime) then use it
only to work out a default `MICROPY_HW_FLASH_MAX_FREQ`.

This value can be overridden in board config.

Note that RP2350's default clock is 150MHz, RP2040's is 125MHz and it has
been certified at 200MHz so it's quite possible that
`PICO_FLASH_SPI_CLKDIV` is unreliable even at standard RP2 clocks.

(If flash timings are marginal then this can manifest as instability rather
than outright failure.)

Fixes issue #17375.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-06-17 11:40:42 +10:00
Meir Armon
c1196cadb1 esp32/modesp32: Fix access to ext0_pin only if defined.
In different functions `machine_rtc_config.ext0_pin` is accessed where
SOC_PM_SUPPORT_EXT0_WAKEUP is not defined, fix that.

Signed-off-by: Meir Armon <meirarmon@gmail.com>
2025-06-17 10:31:41 +10:00
Jeff Epler
b6b7d64bd9 py/modio: Fix the case where write fails in BufferedWriter.flush.
Previously, there was no test coverage of the "write failed" path.  In
fact, the assertion would fire instead of gracefully raising a Python
exception.

Slightly re-organize the code to place the assertion later.  Add a test
case which exercises all paths, and update the expected output.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-17 10:15:59 +10:00
Jeff Epler
5ade8b7058 tests/extmod: Add platform_basic.py for basic coverage test of platform.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 23:37:17 +10:00
Jeff Epler
5901b8d149 tests/cpydiff: Document complex() parsing difference.
In #17384 it was decided that fixing this difference was not worth the code
size increase.  So document it instead.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 23:34:34 +10:00
Jeff Epler
841acb9df1 github/workflows: Add sanitize_undefined workflow to unix port CI.
gcc's "undefined behavior" sanitizer can catch a range of misbehaviors at
runtime that normally go unnoticed.  These include integer and pointer
operations that are "undefined" per the relevant C specification.

This commit enables undefined behavior detection during a new unix
coverage-like build.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 23:28:34 +10:00
Jeff Epler
268264fe64 tools/ci.sh: Add functions for sanitizer builds.
Includes both undefined and address sanitizer configurations.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 23:28:08 +10:00
Jeff Epler
2c8ccd3ee8 py: Fix undefined left shift operations.
By ensuring the value to be shifted is an unsigned of the appropriate type.

This fixes several runtime diagnostics such as:

    ../../py/binary.c:199:28: runtime error:
     left shift of 32768 by 16 places
     cannot be represented in type 'int'

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 23:27:50 +10:00
Chris Webb
816246836e docs/rp2: Document the new rp2 Timer hard= option.
Signed-off-by: Chris Webb <chris@arachsys.com>
2025-06-16 12:35:51 +01:00
Chris Webb
8f85edad86 tests/ports/rp2: Add tests for rp2-specific timer options.
Add tests for both one-shot and periodic timers using the rp2-specific
tick_hz= and hard= parameters.

Signed-off-by: Chris Webb <chris@arachsys.com>
2025-06-16 12:35:51 +01:00
Chris Webb
7816b1f513 rp2/machine_timer: Support hard IRQ timer callbacks.
Unlike some boards like stm32, timer callbacks on the rp2 port are
unconditionally dispatched via mp_sched_schedule(), behaving like
soft IRQs with consequent GC jitter and delays.

Add a 'hard' keyword argument to the rp2 Timer constructor and init.
This defaults to False but if it is set True, the timer callback will
be dispatched in hard IRQ context rather than queued.

Signed-off-by: Chris Webb <chris@arachsys.com>
2025-06-16 12:35:51 +01:00
Andrew Leech
cfcc53da72 drivers/esp-hosted: Replace EVENT_POLL_HOOK with mp_event_wait_ms.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2025-06-16 16:36:39 +10:00
Andrew Leech
573180f788 renesas-ra: Replace MICROPY_EVENT_POLL_HOOK with mp_event_wait.
Basic update to the renesas-ra port to replace the traditional
`MICROPY_EVENT_POLL_HOOK` with the newer mp_event_wait API as appropriate.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2025-06-16 16:36:31 +10:00
Damien George
d9467b07cb tools/mpremote: Improve df command to use new no-arg vfs.mount() query.
The existing `mpremote df` command is not very good, because it needs to
assume that all directories in the root directory are mount points, and
also doesn't correctly stat filesystems when the current directory is not
the root. This leads to wrong results

With the introduction of `vfs.mount()` to return a list of mounted
filesystems and their path, a much better df can be implemented, as done in
this commit.

The new df will also fall back to using the old approach of listing the
root directory if the no-arg `vfs.mount()` query is not supported.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-16 15:11:24 +10:00
Meir Armon
171d751242 esp32/modesp32: Make wake_on_ext1 available only on SoCs supporting it.
The `esp32.wake_on_ext1()` method should only be available on boards that
have SOC_PM_SUPPORT_EXT1_WAKEUP=y.  And update docs to reflect this.

Signed-off-by: Meir Armon <meirarmon@gmail.com>
2025-06-16 14:18:02 +10:00
Meir Armon
4697a06fdb esp32/modesp32: Make wake_on_ext0 available only on SoCs supporting it.
The `esp32.wake_on_ext0()` method should only be available on boards that
have SOC_PM_SUPPORT_EXT0_WAKEUP=y.  And update docs to reflect this.

Signed-off-by: Meir Armon <meirarmon@gmail.com>
2025-06-16 14:17:14 +10:00
Meir Armon
cb315bb8e4 esp32/modesp32: Make wake_on_touch available only on SoCs supporting it.
The `esp32.wake_on_touch()` method should only be available on boards that
have SOC_TOUCH_SENSOR_SUPPORTED=y.  And update docs to reflect this.

Signed-off-by: Meir Armon <meirarmon@gmail.com>
2025-06-16 14:16:16 +10:00
Jeff Epler
5ff2ae5a6c py/asmbase: Fix assertion error with viper code.
In the case of viper code it's possible to reach MP_ASM_PASS_EMIT with a
code size of 0 bytes.  Update the assertion accordingly.

After this change, `mpy-cross -march=debug' on viper tests no longer
crashes.

Fixes issue #17467.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 14:02:30 +10:00
Jeff Epler
fc6205c4f0 unix/coverage: Add coverage test for left adjusted print.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 13:59:57 +10:00
Jeff Epler
1a8f4b290b py/mpprint: Remove unused "PF_FLAG_NO_TRAILZ" flag.
Looking at the git history, there's no indication that the
`PF_FLAG_NO_TRAILZ` flag was ever implemented or that "%!" was used as an
`mp_printf` format string in practice.

So remove the flag and re-number the other flags.

Leave `PF_FLAG_SEP_POS` at 9 (the highest position that probably works with
16-bit integers like the pic16bit port).

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 13:58:13 +10:00
Jeff Epler
73b1cbc17a py/objlist: Reduce code size in slice operations.
By refactoring the code to separate out the slicing operation from the
regular indexing operation, code can be shared between the various types of
slice operations (read/assign/delete).

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 13:43:47 +10:00
Jeff Epler
0ef5ede382 py/mpz: Avoid undefined behavior decrementing NULL.
In the case where an mpz number is zero, its `len` is 0 and its `dig` is
NULL.  In that case, decrementing NULL via `d--` is undefined behavior
according to the C specification.

Restructuring the loops in this way avoids undefined behavior.

Also, ensure that these cases are tested in the coverage test.  This
doesn't make much difference now, but would otherwise cause errors later
when the undefined behavior sanitizer is employed in CI.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-16 12:11:07 +10:00
Meir Armon
42404b5588 esp32/modesp32: Make wake_on_ulp available only on SoCs that support it.
The `esp32.wake_on_ulp()` method should only be available on boards that
have SOC_ULP_SUPPORTED=y.  Update docs to reflect this.

Signed-off-by: Meir Armon <meirarmon@gmail.com>
2025-06-16 11:24:25 +10:00
Damien George
fa393feaed esp32/README: Update README to describe auto filesystem sizing.
Signed-off-by: Damien George <damien@micropython.org>
2025-06-14 01:06:27 +10:00
Damien George
6201e77999 esp32/boards: Convert all boards to auto detect flash size.
Remove the "vfs" entry from all partitions-*.csv files, and then remove
duplicated files.

And remove the ESP32_GENERIC_S3-FLASH_4M variant, because it's no longer
needed.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-14 01:06:12 +10:00
Damien George
2a0e2b5782 esp32/main: Auto detect the size of flash and auto create vfs partition.
Currently in the esp32 port the size of the SPI flash must be configured at
build time, eg 4MiB, 8MiB, etc.  Also, the esp32 partition table must be
configured at build time, which depends on the size of the SPI flash.  A
bigger flash means more can be allocated to the user filesystem.

This commit makes it so the SPI flash size is automatically determined at
runtime, and the filesystem size is automatically set to take up as much
room as possible (a "vfs" partition is created automatically if it doesn't
exist).

This works by:
- Setting the SPI flash size to be 4MiB in the build (or some other value,
  as long as the firmware app fits).
- Removing the vfs partition from the esp32 partition table (only nvs,
  phy_init and firmware, and maybe romfs, remain in the partition table).
- At boot, query the physical size of the SPI flash and use that as the
  actual size in the code.
- If it doesn't already exist, automatically create a "vfs" partition which
  takes up the flash from the end of all existing partitions to the end of
  flash.

This allows simplifying a lot of board configurations, and removing some
board variants that just change the flash size (to be done in a following
commit).

It's also fully backwards compatible, in the following sense:
- Existing boards with MicroPython firmware will continue to work with the
  same filesystem, ie the filesystem won't be erased when the firmware is
  updated.
- If a user has a custom esp32 partition table and installs MicroPython as
  a bare app into the app partition, the new MicroPython firmware will
  honour the esp32 partition table and use either "vfs" or "ffat"
  partitions as the filesystem.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-14 01:03:44 +10:00
Damien George
398da22492 esp8266/modmachine: Use common machine_time_pulse_us implementation.
Testing shows that for frequencies which the esp8266 can handle -- up to
about 1kHz -- `machine.time_pulse_us()` now gives more accurate results.

Prior to this commit it would measure on average about 1us lower, but now
the average is much closer to the true value.  For example a pulse that is
1000us long, it would measure between 998 and 1000us.  Now it measures
between 999us and 1001us.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-13 16:27:35 +10:00
Damien George
ef21ade602 extmod/machine_pulse: Optimise time_pulse_us for code size.
This implementation is based on the esp8266 custom implementation, and
further optimised for size and accuracy.

Testing on PYBD_SF2 and RPI_PICO2_W shows that it is at least as good as
the original implementation in performance.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-13 16:27:35 +10:00
Damien George
5676b45cbb tests/run-natmodtests.py: Consider a test skipped if mpy doesn't exist.
This is different to a test not being run because there is no corresponding
natmod at all.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-12 21:53:31 +10:00
Damien George
63701c2e94 tests/run-perfbench.py: Create a _result.json at end of run.
Reuse the `create_test_report()` function from `run-tests.py` to generate a
`_result.json` file summarising the test run.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-12 21:53:31 +10:00
Damien George
09b058559b tests/run-natmodtests.py: Create a _result.json at end of run.
Reuse the `create_test_report()` function from `run-tests.py` to generate a
`_result.json` file summarising the test run.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-12 21:53:31 +10:00
Damien George
6db9c80856 tests/run-multitests.py: Create a _result.json at end of run.
Reuse the `create_test_report()` function from `run-tests.py` to generate a
`_result.json` file summarising the test run.  If there's more than one
permutation of the test run, only the last result is saved.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-12 21:53:25 +10:00
Damien George
2bc5af6945 tests/run-tests.py: Factor out helper function to create test report.
This commit factors existing code in `run-tests.py` into a new helper
function `create_test_report()`.  That function prints out a summary of the
test run (eg number of tests passed, number failed, number skipped) and
creates the corresponding `_results.json` file.

This is done so `create_test_report()` can be reused by the other test
runners.

The `test_count` counter is now gone, and instead the number of passed plus
number of failed tests is used as an equivalent count.

For consistency this commit makes a minor change to the printed output of
`run-tests.py`: instead of printing a shorthand name for tests that failed
or skipped, it now prints the full name.  Eg what was previously printed as
`attrtuple2` is now printed as `basics/attrtuple2.py`.  This makes the
output a little longer (when there are failed/skipped tests) but helps to
disambiguate the test name, eg which directory it's in.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-12 21:47:20 +10:00
Damien George
e4d556b149 tests/extmod/random_extra_float.py: Skip when funcs not available.
This test was factored out from `random_extra.py` back in commit
6572029dc0, and the skip logic copied from
that file.  But the skip logic needs to test that the `random` and
`uniform` functions exist, not `randint`.

This commit fixes that skip logic.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-12 21:45:40 +10:00
Damien George
9bde12597a github/workflows: Use windows-latest runner for all Windows CI jobs.
The windows-2019 runner has been deprecated by GitHub, so stop using that.
Also take the chance to stop using windows-2022 and just use windows-latest
everywhere.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-11 00:43:40 +10:00
Damien George
ca80aabf21 py/objfloat: Change MSVC workaround for NAN being a constant.
It's actually a bug in the Windows SDK, not MSVC, as per
https://stackoverflow.com/questions/79195142/recent-msvc-versions-dont-treat-nan-as-constant-workaround/79324199#79324199

Thanks to @stinos.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-11 00:43:31 +10:00
Jeff Epler
2ce63b1420 py/parsenum: Fix parsing complex literals with negative real part.
If a complex literal had a negative real part and a positive imaginary
part, it was not parsed properly because the imaginary part also came out
negative.

Includes a test of complex parsing, which fails without this fix.

Co-authored-by: ComplexSymbol <141301057+ComplexSymbol@users.noreply.github.com>
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-10 15:41:24 +10:00
Jeff Epler
0a98f3a911 py/objarray: Allow extending array with any iterable.
As suggested by @dpgeorge, factor out part of array_construct to allow it
to be used for construction & extension.

Note that extending with a known-length list (or tuple) goes through the
slow path of calling array_extend once per element.

Fixes issue #7408.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-10 15:32:54 +10:00
Jeff Epler
c1629dc2ff py/parsenum: Further reduce code size in check for inf/nan.
A few more bytes can be saved by not using nested `if`s (4 bytes for
`build-MICROBIT/py/parsenum.o`, 8 bytes for RPI_PICO firmware).

This commit is better viewed with whitespace changes hidden, because
two blocks were reindented (e.g., `git show -b`).

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-10 15:22:34 +10:00
Jeff Epler
5eb9755259 py/parsenum: Reduce code size in check for inf/nan.
By avoiding two different checks of the string length, code size is reduced
without changing behavior: Some invalid float/complex strings like "ix"
will get handled just like "xx" in the main number literal parsing code
instead.

The optimizer alone couldn't remove the reundant comparisons because it
couldn't make a transformation that let an invalid string like "ix" pass
into the generic number parsing code.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-10 15:21:18 +10:00
Jeff Epler
745bec9ce3 extmod/modre: Use specific error message if regex is too complex.
If the error reporting mode is at least "normal", report a failure due to a
complex regex with a different message.

Fixes issue #17150.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-10 15:14:56 +10:00
Damien George
17951cee87 py/dynruntime.mk: Enable single-precision float by default on armv6/7m.
Soft float now works on these ARM targets thanks to the parent commit.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-10 13:43:03 +10:00
Damien George
718ff4fdd5 tools/mpy_ld.py: Support R_ARM_ABS32 relocation in text.
Add support for R_ARM_ABS32 relocations in native .mpy files.  These can be
rewritten in the same way that data relocations are.

Fixes issue #14430.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-10 13:40:11 +10:00
Damien George
5f4abeb385 py/asmthumb: Implement long jumps on Thumb/armv6m architecture.
With this change, all tests (except thread tests) now pass on RPI_PICO when
using the native emitter:

    (plug in RPI_PICO)
    $ cd tests
    $ ./run-tests.py -t a0 --via-mpy --emit native

Signed-off-by: Damien George <damien@micropython.org>
2025-06-10 13:14:06 +10:00
Alessandro Gatti
43f6013294 py/asmxtensa: Extend BCC range to 18 bits.
This commit lets the native emitter backend extends the range of the
BCC family of opcodes (BALL, BANY, BBC, BBS, BEQ, BGE, BGEU, BLT,
BLTU, BNALL, BNE, BNONE) from 8 bits to 18 bits.

The test suite contains some test files that, when compiled into native
code, would require BCC jumps outside the (signed) 8 bits range.  In
this case either the MicroPython interpreter or mpy-cross would raise an
exception, not running the test when using the "--via-mpy --emit native"
command line options with the test runner.

This comes with a 3 bytes penalty on each forward jump, bringing the
footprint of those jumps to 6 bytes each, as a longer opcode sequence
has to be emitted to let jumps access a larger range.  However, this is
slightly offset by the fact that backward jumps can be emitted with a
single opcode if the range is small enough (8-bits offset).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 12:28:29 +10:00
Alessandro Gatti
80b823bca1 py/asmxtensa: Extend BCCZ range to 18 bits.
This commit lets the native emitter backend extends the range of the
BCCZ family of opcodes (BEQZ, BNEZ, BLTZ, BGEZ) from 12 bits to 18
bits.

The test suite contains some test files that, when compiled into native
code, would require BCCZ jumps outside the (signed) 12 bits range.  In
this case either the MicroPython interpreter or mpy-cross would raise an
exception, not running the test when using the "--via-mpy --emit native"
command line options with the test runner.

This comes with a 3 bytes penalty on each forward jump, bringing the
footprint of those jumps to 6 bytes each, as a longer opcode sequence
has to be emitted to let jumps access a larger range.  However, this is
slightly offset by the fact that backward jumps can be emitted with a
single opcode if the range is small enough (3 bytes for a 12-bits
offset).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 12:28:29 +10:00
Alessandro Gatti
0da22b2c30 tools/ci.sh: Fix nanbox CI test runs.
This commit fixes CI test runs for the `nanbox` target, which were
broken by the unconditional native emitter code output changes in the
test runner.

The `nanbox` configuration does not enable native emitters of any kind,
and with a full test run that includes executing emitted native code
things would break when doing CI runs.

This is worked around by introducing a common subset of tests that do
not involve the native emitter, and a more comprehensive set of tests
that include both non-emitter and emitter tests.  The `nanbox` CI test
run will stop at the first subset, whilst other configurations will run
that and execute further tests.

Function names have been kept the same for steps that involve native
code, with the `nanbox` subset having another one.  This should not
trigger any breakage in existing CI configurations or external scripts.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Alessandro Gatti
c1c73d966e tests/run-tests.py: Unconditionally enable native tests if asked.
This commit lets the test runner enumerate and run native tests if the
feature check fails but native tests were explicitly requested from the
command line.

The old behaviour would disable native tests anyway if the feature check
failed, however this hid a bug in the x86 native emitter that would be
triggered even during the feature check.  That meant the test suite
would pass on x86 even with a broken emitter, as those tests would have
been skipped anyway.

Now, if the user asks for native code it will get native code out of the
runner no matter what.

Co-authored-by: Damien George <damien@micropython.org>
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Alessandro Gatti
5b90d6d418 py/asmarm: Give a proper name to the temporary register.
This commit performs a small refactoring on the Arm native emitter, by
renaming all but one instance of ASM_ARM_REG_R8 into REG_TEMP.

ASM_ARM_REG_R8 is the temporary register used by the emitter when
operations cannot overwrite the value of a particular register and some
extra storage is needed.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Alessandro Gatti
bbab2e98f5 py/asmarm: Extend int-indexed 32-bit load/store offset ranges.
This commit extends the range for int-indexed load/store opcode
generators, making them emit correct code sequences for offsets that
span more than 12 bits.

This is necessary due to those generator bits being also used in the
Viper emitter, where it's more probable to reference offsets that can
not be embedded in the LDR/STR opcodes.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Alessandro Gatti
901c96dc55 py/emitnative: Remove redundant RV32 Viper int-indexed code.
This commit removes redundant RV32 implementations of certain
int-indexed code generation operations (32-bit load/store and 16-bit
load).

Those operations were already available as part of the native emitter
API but were not exposed to the Viper code generator.  As part of the
introduction of more specialised load and store API calls to
int-indexed Viper load/store generator bits, the existing native emitter
implementations are reused, thus making the Viper implementations
redundant.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Alessandro Gatti
84ad2c6cd0 py/asmxtensa: Extend existing specialised load/store operations range.
This commit updates the existing specialised implementations for
int-indexed 32-bit load and store operations, and adds a specialised
implementation for int-indexed 16-bit load.

The 32-bit operations relied on the fact that their applicability was
limited to a specific range, falling back on a generic implementation
otherwise.  Introducing a single entry point for each int-indexed
load/store operation size would break that assumption.  Now those two
operations contain fallback code to generate working code by themselves
instead of raising an exception.

The 16-bit operation instead simply did not have any range check, but it
was not exposed directly to the Viper emitter.  When a 16-bit
int-indexed load entry point was introduced, the existing implementation
would fail when accessing memory outside its 0..255 halfwords range.  A
specialised implementation is now present, performing fewer operations
than the existing Viper emitter equivalent.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Alessandro Gatti
1f5ba6998b py/asmthumb: Extend load/store generators with ARMv7-M opcodes.
This commit lets the Thumb native code generator backend emit ARMv7-M
specific opcodes for indexed load/store operations if possible.

Now T3 opcode encodings are used if the generator backend is configured
to allow emitting ARMv7-M opcodes and if the (unsigned) scaled index
fits in 12 bits.  Or, in other words, LDR{B,H}.W and STR{B,H}.W opcodes
are now emitted if possible.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Alessandro Gatti
78ee1bac60 py/emitnative: Let Viper int-indexed code use appropriate operands.
This commit extends the generic ASM API by adding the rest of the
ASM_{LOAD,STORE}[size]_REG_REG_OFFSET macros whenever applicable.

The Viper int-indexed load/store code generator was changed to use those
API functions if they are available, falling back to backend-specific
implementations if possible and ultimately to a generic implementation.

Right now all backends except for x64 implement load16, load32, and
store32 operations (x64 only implements load16).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 11:29:02 +10:00
Jeff Epler
e43a3849d9 lib/berkeley-db-1.xx: Update submodule to latest.
Fixes a memory leak in the case lseek fails when creating the mpool.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-06-10 11:24:50 +10:00
Andrew Leech
fffaf8a41f extmod/modnetwork: Consolidate definition of common drivers.
Most extmod network drivers were being defined on a per-port basis,
duplicating code and making enabling a driver on a new port harder.

This consolidates extmod driver declarations and removes the existing
per-port definitions of them.

This commit has been verified to be a no-op in terms of firmware change.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-10 11:20:38 +10:00
Andrew Leech
95203ab88b tools/boardgen.py: Ensure board pin locals_dict has consistent order.
`tools/boardgen.py` is used by the `make-pins.py` scripts in many ports to
generate the pin definitions for the machine module.

In #17391 it was found that this is currently generating the C structs for
board pin definitions with inconsistent ordering (across different build
runs), which makes it sometimes impossible to get a consistent binary file
even for no change in source files.

This commit fixes that by sorting the board pin names alphabetically.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-10 11:09:14 +10:00
Alessandro Gatti
b8e56a17b1 github/workflows: Split QEMU/Arm builds into separate entries.
This commit takes the QEMU/Arm CI build and test step and splits it into
three separate steps (bigendian, sabrelite, thumb), to allow them to run
in parallel.

Currently the QEMU/Arm CI build step would take up to 16 minutes, often
being the last step blocking a full test run.  With this commit, when
the steps run in parallel the time it takes to complete the QEMU/Arm
build and test procedure is cut in half - taking between 8 to 9 minutes
depending on the CI runner load.

The existing `ci_build_and_test_arm` function has been removed, in
favour of having three separate functions - one per configuration.  They
are called `ci_build_and_test_arm_bigendian`,
`ci_build_and_test_arm_sabrelite`, and `ci_build_and_test_arm_thumb`.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-10 10:57:32 +10:00
purewack
5f058e9863 esp32: Update ADC driver update to the new esp_adc API.
This commit updates the ADC to use the new driver `esp_adc/adc_oneshot.h`.

There are several errata notes about not being able to change the bit-width
of the ADCs certain chips.  The only chip that can switch resolution to a
lower one is the normal ESP32.  ESP32 C2 and S3 are stuck at 12 bits, while
S2 is at 13 bits.

On the S2, you can change the resolution, but it has no effect on the
resolution, rather, it prevents attenuation from working at all!

The resolution is set to the maximum possible for each SoC, with the ESP32
being the only one not throwing errors when trying to set the bit-width to
9, 10, 11 or 12 bits using `ADC.width(bits)`.

Signed-off-by: Damian Nowacki (purewack) bobimaster15@gmail.com
2025-06-05 17:01:51 +10:00
Daniël van de Giessen
2c2f0b292a esp32: Re-use allocated timer interrupts and simplify UART timer code.
If the interrupt is not freed but merely disabled, instead of reallocating
it every time the timer is enabled again we can instead just re-enable it.
That means we're no longer setting the handler every time, and we need to
ensure it does not change. Doing so by adding an additional wrapper
function does not only solve that problem, it also allows us to remove
some code duplication and simplify how machine_uart uses the timer.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-06-05 16:39:13 +10:00
Daniël van de Giessen
bf909303ff esp32/machine_timer: Do not free interrupt from ISR.
esp_intr_free is not safe to call from the timer ISR because it requires
the current task (the one the ISR interrupted) to be pinned to the same
core as the interrupt was allocated on. Merely disabling the ISR however is
safe since that only requires that we're currently running on the same core
(which the ISR always is), regardless of the current task.

This was causing deadlocks in machine_uart when the ISR happened to
interrupt a task that was not pinned to a specific core.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-06-05 16:39:13 +10:00
Damien George
5b340b12b8 tests/run-tests.py: Remove filename arg from prepare_script_for_target.
It's no longer used.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-05 15:18:30 +10:00
Damien George
229104558f tests/run-tests.py: Automatically skip tests that are too large.
Some tests are just too big for targets that don't have much heap memory,
eg `tests/extmod/vfs_rom.py`.  Other tests are too large because the target
doesn't have enough IRAM for native code, eg esp8266 running
`tests/micropython/viper_args.py`.

Previously, such tests were explicitly skipped on targets known to have
little memory, eg esp8266.  But this doesn't scale to multiple targets, nor
to more and more tests which are too large.

This commit addresses that by adding logic to the test runner so it can
automatically skip tests when they don't fit in the target's memory.  It
does this by prepending a `print('START TEST')` to every test, and if a
`MemoryError` occurs before that line is printed then the test was too big.
This works for standard tests, tests that go via .mpy files, and tests that
run in native emitter mode via .mpy files.

For tests that are too big, it prints `lrge  <test name>` on the output,
and at the end prints them on a separate line of skipped tests so they can
be distinguished.  They are also distinguished in the `_result.json` file
as a skipped test with reason "too large".

Signed-off-by: Damien George <damien@micropython.org>
2025-06-05 15:15:31 +10:00
Damien George
4c55b0879b tools/ci.sh: Allow errors in code-size build to fail the CI.
It was possible for CI to pass even if the bare-arm port fails to build.
This commit fixes that.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-05 14:57:23 +10:00
Alessandro Gatti
193603dbac tools/ci.sh: Clean the correct MPY files when batch compiling.
This commit fixes a small yet harmless issue that occurs when invoking
`ci_native_mpy_modules_build` on a persistent environment, as only X64
MPY files would be removed by the cleaning process.

Now the correct architecture is passed at all times when cleaning before
building a natmod for a particular architecture, forcing a full build of
all files to better simulate the CI environment (where there's no state
persisted between runs for this step).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:40 +10:00
Alessandro Gatti
e8c92240e2 tools/ci.sh: Remove natmod build restrictions for Xtensa.
This commit lets the CI pipeline build all natmods for the Xtensa
target, now that ROM symbols can be used in the linking process.

The restriction was put in place due to build failures on certain
natmods for Xtensa, as ROM symbols would not be used, causing undefined
symbol errors at build time.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Alessandro Gatti
e4c0e2b73d esp8266/main: Print error information on crash-induced reboots.
This commit adds an optional configuration option for the ESP8266 port
that, if the board rebooted due to a crash, will print to stdout some
information about the error that triggered the issue.

It is not possible using regular SDK functions to intercept errors and
print information at that stage, and the only error response from the
board is to reboot itself.  This is the next best thing, print some
error information just once at boot time after the crash - the least
invasive option given the situation we're in.

This is disabled by default, and can be enabled by enabling
MICROPY_HW_HARD_FAULT_DEBUG in the port configuration - obviously with a
small increase in the firmware code footprint.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Alessandro Gatti
4227654d42 examples/natmod/btree: Fix build for Xtensa.
This commit provides the appropriate external symbol addresses to let
the "btree" example natmod build for the Xtensa platform.

On the ESP8266, unsigned integer division code isn't provided as part of
libgcc.a, libm.a, or libc.a, but it is instead provided by the ROM.
Regular builds inject the appropriate symbol addresses as part of the
linking process (see eagle.rom.addr.v6.ld), but natmods need this
information brought in from somewhere else.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Alessandro Gatti
887125fc58 examples/natmod/deflate: Fix build for Xtensa.
This commit provides the appropriate external symbol addresses to let
the "deflate" example natmod build for the Xtensa platform.

Unlike other natmods that require an external symbol list to build
without bringing in the whole runtime libraries set, this natmod is
referencing the `__modsi3` symbol which was removed from the ESP8266's
SDK but not present in ROM.  The latter only has a `__umodsi3`
implementation that only operates on unsigned values, and thus unable to
handle this natmod.  Thus, the extended library resolution process is
enabled for this natmod as a `__modsi3` implementation is made available
that way (still using ROM symbols whenever possible).  This also means
that symbols that appear in both ROM and external libraries sort of
co-exist in the final MPY file, with ROM symbols being used by natmod
code but the implementation from the library still exists in the final
MPY file, unused.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Alessandro Gatti
462ee12d3c examples/natmod/framebuf: Fix build for Xtensa.
This commit provides the appropriate external symbol addresses to let
the "framebuf" example natmod build for the Xtensa platform.

On the ESP8266, integer division code isn't provided as part of
libgcc.a, libm.a, or libc.a, but it is instead provided by the ROM.
Regular builds inject the appropriate symbol addresses as part of the
linking process (see eagle.rom.addr.v6.ld), but natmods need this
information brought in from somewhere else.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Alessandro Gatti
0bf2fd7ad0 examples/natmod/random: Fix build for Xtensa.
This commit provides the appropriate external symbol addresses to let
the "random" example natmod build for the Xtensa platform.

On the ESP8266, signed integer division code isn't provided as part of
libgcc.a, libm.a, or libc.a, but it is instead provided by the ROM.
Regular builds inject the appropriate symbol addresses as part of the
linking process (see eagle.rom.addr.v6.ld), but natmods need this
information brought in from somewhere else.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Alessandro Gatti
9ef7322a5d tests/run-natmodtests.py: Allow injected code customisation.
This commit introduces a mechanism to customise the code that is
injected to the board when performing a native module import.

A new argument, "-b"/"--begin", is added so regular Python code can be
inserted in the injected fragment between the module file creation and
the effective module import.  This is needed for running natmod tests on
ESP8266 as that board does not have enough memory to fit certain modules
unless additional configuration is performed.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Alessandro Gatti
bf2005de9e tools/mpy_ld.py: Resolve fixed-address symbols if requested.
This commit lets mpy_ld.py resolve symbols not only from the object
files involved in the linking process, or from compiler-supplied static
libraries, but also from a list of symbols referenced by an absolute
address (usually provided by the system's ROM).

This is needed for ESP8266 targets as some C stdlib functions are
provided by the MCU's own ROM code to reduce the final code footprint,
and therefore those functions' implementation was removed from the
compiler's support libraries.  This means that unless `LINK_RUNTIME` is
set (which lets tooling look at more libraries to resolve symbols) the
build process will fail as tooling is unaware of the ROM symbols'
existence.  With this change, fixed-address symbols can be exposed to
the symbol resolution step when performing natmod linking.

If there are symbols coming in from a fixed-address symbols list and
internal code or external libraries, the fixed-address symbol address
will take precedence in all cases.

Although this is - in theory - also working for the whole range of ESP32
MCUs, testing is currently limited to Xtensa processors and the example
natmods' makefiles only make use of this commit's changes for the
ESP8266 target.

Natmod builds can set the MPY_EXTERN_SYM_FILE variable pointing to a
linkerscript file containing a series of symbols (weak or strong) at a
fixed address; these symbols will then be used by the MicroPython
linker when packaging the natmod.  If a different natmod build method is
used (eg. custom CMake scripts), `tools/mpy_ld.py` can now accept a
command line parameter called `--externs` (or its short variant `-e`)
that contains the path of a linkerscript file with the fixed-address
symbols to use when performing the linking process.

The linkerscript file parser can handle a very limited subset of
binutils's linkerscript syntax, namely just block comments, strong
symbols, and weak symbols.  Each symbol must be in its own line for the
parser to succeed, empty lines or comment blocks are skipped.  For an
example of what this parser was meant to handle, you can look at
`ports/esp8266/boards/eagle.rom.addr.v6.ld` and follow its format.

The natmod developer documentation is also updated to reflect the new
command line argument accepted by `mpy_ld.py` and the use cases for the
changes introduced by this commit.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-06-04 22:35:39 +10:00
Damien George
9174cffc47 mpy-cross/main: Document emit=host option in help.
Signed-off-by: Damien George <damien@micropython.org>
2025-06-04 12:07:30 +10:00
Damien George
e869dae31e mpy-cross/main: Exit with error if arch not specified with emit=native.
Currently, mpy-cross will crash if called as:

    mpy-cross -X emit=native foo.py

because it tries to use the native emitter with no target architecture set.

Fix that by checking that an architecture is set when `-X emit=native` or
`-X emit=viper` is used.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-04 12:06:12 +10:00
Andrew Leech
820485358d unix/coverage: Add coverage test for mp_sched_schedule_node.
Test modified to reschedule itself based on a flag setting. Without the
change in the parent commit, this test executes the callback indefinitely
and hangs but with the change it runs only once each time
mp_handle_pending() is called.

Modified-by: Angus Gratton <angus@redyak.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-04 11:31:12 +10:00
Angus Gratton
7f274c7550 py/scheduler: Only run scheduler callbacks queued before run started.
Without this change, a scheduler callback which itself queues a new
callback will have that callback executed as part of the same scheduler
run. Where a callback may re-queue itself, this can lead to an infinite
loop.

With this change, each call to mp_handle_pending() will only service the
callbacks which were queued when the scheduler pass started - any callbacks
added during the run are serviced on the next mp_handle_pending().

This does mean some interrupts may have higher latency (as callback is
deferred until next scheduler run), but the worst-case latency should stay
very similar.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-06-04 11:31:12 +10:00
Damien George
b15348415e extmod/modframebuf: Add support for blit'ing read-only data.
Currently the `FrameBuffer.blit(buf, x, y)` method requires the `buf`
argument to be another `FrameBuffer`, which is quite restrictive because it
doesn't allow blit'ing read-only memory/data.

This commit extends `blit()` to allow the `buf` argument to be a tuple or
list of the form:

    (buffer, width, height, format[, stride])

where `buffer` can be anything with the buffer protocol and may be
read-only, eg `bytes`.

Also, the palette argument to `blit()` may be of the same form.

The form of this tuple/list was chosen to be the same as the signature of
the `FrameBuffer` constructor (that saves quite a bit of code size doing it
that way).

Signed-off-by: Damien George <damien@micropython.org>
2025-06-04 02:40:45 +10:00
Andrew Leech
d5f2fc239a extmod/modbluetooth: Add timeout to deinit.
If the BLE radio stops responding before deinit is called the function can
get stuck waiting for an event that is never received, particularly if the
radio is external or on a separate core.

This commit adds a timeout, similar to the timeout already used in the init
function.  Updated for nimble, btstack, esp32 and zephyr bindings.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-04 02:21:32 +10:00
Andrew Leech
17898f8607 stm32/machine_adc: Enable ADC re-read errata handling for STM32WB55.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-04 02:11:23 +10:00
Matt Trentini
3e33d0567f ports: Update board.json files for vendor/product consistency.
The vendor and product fields in the `board.json` files were somewhat
inconsistent.  Remove any duplication of the vendor name in the product
field so that `f"{vendor} {product}"` reads well.

In addition to that, update most of the URL's for `board.json` files that
are modified here, and match case and spacing used by the manufacturers for
the vendor and product names.

Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2025-06-04 01:47:59 +10:00
Angus Gratton
ba92063d64 docs: Add a description of recv/recvfrom flags argument.
Implementation added for various ports in the parent commits.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-06-03 12:52:25 +10:00
Angus Gratton
d23fb86934 tests/multi_net: Add test coverage for socket recv flag MSG_DONTWAIT.
Adding multi_net case for UDP only, as TCP timing is hard to test reliably.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-06-03 12:52:25 +10:00
Angus Gratton
73d4ddce6c tests/multi_net: Add test coverage for socket recv flag MSG_PEEK.
Adds TCP and UDP multi_net test cases.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-06-03 12:52:22 +10:00
Angus Gratton
0b224048ef unix/modsocket: Expose MSG_PEEK flag for recv & recvfrom.
This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-06-03 12:52:06 +10:00
Angus Gratton
4781cde4f7 esp32/modsocket: Add optional flags argument for recv and recvfrom.
Implements MSG_PEEK and MSG_DONTWAIT (both passed through to LWIP
sockets API).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-06-03 12:52:06 +10:00
Angus Gratton
e8447768ef extmod/modlwip: Add optional flags argument for recv and recvfrom.
Implements MSG_PEEK and MSG_DONTWAIT.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-06-03 12:52:02 +10:00
Damien George
4dff9cbf1a tests/run-tests.py: Change _results.json to have a combined result list.
The `_results.json` output of `run-tests.py` was recently changed in
7a55cb6b36 to add a list of passed and
skipped tests.

The way this was done turned out to be not general enough, because we want
to add another type of result, namely tests that are skipped because they
are too large.

Instead of having separate lists in `_results.json` for each kind of result
(pass, fail, skip, skip too large, etc), this commit changes the output
form of `_results.json` so that it stores a single list of 3-tuples of all
tests that were run:

    [(test_name, result, reason), ...]

That's more general and allows adding a reason for skipped and failed
tests.  At the moment this reason is just an empty string, but can be
improved in the future.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-03 10:07:29 +10:00
Andrew Leech
c0111e63b3 lib/libhydrogen: Update to latest release.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-06-02 21:28:51 +10:00
Damien George
dea3035b88 tools/pyboard.py: Add write_timeout and catch errors in enter_raw_repl.
If the USB serial device locks up, then writes to that device can hang
forever.  That can make the test runner `tests/run-tests.py` lock up, among
other problems.

This commit introduces a 5 second write-timeout, and catches any OSError's
raised during `enter_raw_repl()`.  Now, if a USB serial device locks up,
`enter_raw_repl()` will eventually raise an exception.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-02 17:02:59 +10:00
Damien George
b1c947ab45 tools/pyboard.py: Introduce timeout_overall for read_until().
This applies the mpremote commit 03fe9c55ea
to pyboard.py.

The `timeout_overall` is used in `enter_raw_repl()`.  It prevents waiting
forever for a serial device that does not respond to the Ctrl-C/Ctrl-D/etc
commands and is constantly outputting data.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-02 17:02:30 +10:00
Damien George
aaedd59b7c tools/pyboard.py: Avoid initial blocking read in read_until().
This applies the mpremote commit 0d46e45a1f
to pyboard.py.

If the target does not return any data then `read_until()` will block
indefinitely.  Fix this by making the initial read part of the general read
look, which always checks `inWaiting() > 0` before reading from the serial
device.

Also added the UART timeout to the constructor.  This is not currently used
but may be used as an additional safeguard.

Signed-off-by: Damien George <damien@micropython.org>
2025-06-02 17:02:30 +10:00
Alessandro Gatti
f5d10c322e py/asmxtensa: Emit prologue jump only when constants table is in use.
This commit simplifies native functions' prologue code by not emitting a
jump opcode that goes over the function's constants pool if the pool is
empty.

The original code assumed the constants pool is never empty as large
32-bits constants are commonly used, but for inline assembler functions
that may not be the case.  This meant that inline assembler functions
may start with an unneeded jump (along with its alignment byte), using
four bytes more than necessary.

This commit is limited to the "xtensa" target, as "xtensawin" doesn't
support inline assembler functions yet, so native functions' constant
pools are almost always guaranteed to hold one or more values.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-29 12:12:39 +10:00
Alessandro Gatti
1006ed69f0 py/emitinlinextensa: Add the rest of LX3 opcodes to the assembler.
This commit expands the Xtensa inline assembler to support most if not
all opcodes available on the ESP8266 and LX3 Xtensa cores.

This is meant as a stepping stone to add inline assembler support for
the ESP32 and its LX6 core, along to windowed-specific opcodes and
additional opcodes that are present only on the LX7 core (ESP32-S3 and
later).

New opcodes being added are covered by tests, and the provided tests
were expanded to also include opcodes available in the existing
implementation.  Given that the ESP8266 space requirements are tighter
than ESP32's, certain opcodes that won't be commonly used have been put
behind a define to save some space in the general use case.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-29 12:12:39 +10:00
Alessandro Gatti
555f1cf488 py/asmxtensa: Make the generated code dumper work on mpy-cross.
This commit fixes compilation errors occurring when enabling the Xtensa
code dumper inside mpy-cross.

The original code was meant to dump the code from an Xtensa device
itself, but for debugging the inline assembler this functionality was
also needed off-line.  The changes involve solving a signed/unsigned
mismatch that was not much of a problem for the 8266's gcc version but
made modern compilers complain, and using the printf formatter for
pointers when it comes to printing code addresses.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-29 12:12:39 +10:00
Alessandro Gatti
eccd23feb6 py/asmxtensa: Replace printf messages with exceptions.
This commit removes old raw printf calls happening inside certain branch
opcode emitters, indicating the target label is out of range for the
opcode.  They have been replaced with a RuntimeError being raised in
these cases, using a parameterised qstr instead.

Whilst this technically breaks runtime behaviour expectations, the
generated code would not have worked anyway so it's better to catch
those cases early.  This should be updated to always emit long jumps
unless jumps are backwards and short enough, following the other ports,
but that's something coming later.

This is actually needed because there are test files that do not work
when processed through mpy-cross and entirely converted to native code.
The original implementation would still generate mostly-valid code that
was bound to crash on the device, whilst this change would prevent
invalid code to even be emitted in the first place.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-29 12:12:39 +10:00
robert-hh
5cfafb73da docs/esp32: Mention the use of Timer(0) by UART.IRQ_RXIDLE.
In both the machine.UART and esp32.quickref sections.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-28 12:13:51 +10:00
robert-hh
92c219afd6 docs/esp32/quickref: Mention the different timer counts.
Since the are ESP32 variants with 1, 2 or 4 hardware timers.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-28 12:13:46 +10:00
robert-hh
2f864416c6 docs/library/time: Amend the documentation of time.mktime().
By showing the argument and refer to epoch instead of a fixed date.  The
note about epoch lists the ports using the POSIX epoch.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-28 12:13:28 +10:00
robert-hh
bbdc832ca9 samd/boards: Add two SparkFun SAMD21 boards.
Add support for the boards:
- SparkFun SAMD21 Dev Breakout
- SparkFun RedBoard Turbo

Both boards are SAMD21 based and actively sold by SparkFun.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-28 12:04:42 +10:00
Dryw Wade
6bfb83e30a rp2: Make FLASH LENGTH match PICO_FLASH_SIZE_BYTES in .ld files.
With a fallback to default sizes if `PICO_FLASH_SIZE_BYTES` is not defined.

Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
2025-05-28 11:02:45 +10:00
Herwin Grobben
2dada065ac stm32: Allow QSPI to work on STM32G4.
Adding a QSPI memory chip on a STM32G4 does not work due to some small
issues, which are fixed in this commit:

- Rename QUADSPI1_xxx alt-func names to QUADSPI_xxx, to match the static
  names used in `qspi.c`.

- Enable `mpu.h` macros on G4.

- Don't include I- and D-cache invalidation on G4.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-26 12:40:27 +10:00
Daniël van de Giessen
9dbae39348 lib/littlefs: Update LittleFS to v2.11.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-26 12:17:27 +10:00
Ayush Singh
670b7c9350 zephyr/boards: Add support for BeaglePlay CC1352p7.
- Enable support for FLASH and IEEE802154 subg radio
- Requires Zephyr v3.8.0

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2025-05-26 12:13:04 +10:00
Angus Gratton
b36111b12c nrf: Revert "nrf/Makefile: Enable LTO by default only on newer gcc.".
This reverts commit 62e0fa04a7.

Reverting as the only linker wrap needed for nrf port was removed
in the parent commit.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-26 11:15:33 +10:00
Angus Gratton
22f1d76633 shared/tinyusb: Use device event hook to schedule USB task.
Previously MicroPython ports would linker-wrap dcd_event_handler
in order to schedule the USB task callback to run when needed.

TinyUSB 0.16 added proper support for an event hook to do the
same thing without the hacky linker wrapping.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-26 11:15:33 +10:00
Damien George
49f81d5046 tests/float/math_constants.py: Test actual e and pi constant values.
The existing test for `math.e` and `math.pi` constants can fail on certain
targets if the functions `math.exp()` and/or `math.cos()` are not accurate
enough (eg out by an LSB of float precision).  For example this test
currently fails on PYBD_SF6 which uses double precision floats (and that's
due to the `lib/libm_dbl/exp.c` implementation not being exact).

This commit changes this constant test so that it tests the actual constant
value, not the evaluation of `exp()` and `cos()` functions.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-22 17:19:03 +10:00
Malcolm McKellips
dc1af386a8 esp32/boards/SPARKFUN_IOT_REDBOARD_ESP32: Add SparkFun board.
Add board definition files for SparkFun IoT RedBoard ESP32.

Signed-off-by: Malcolm McKellips <malcolm.mckellips@sparkfun.com>
2025-05-22 10:37:38 +10:00
Malcolm McKellips
7f6fedef2a rp2/boards/SPARKFUN_XRP_CONTROLLER_BETA: Fix default I2C to use I2C1.
Signed-off-by: Damien George <damien@micropython.org>
2025-05-22 00:24:02 +10:00
Phil Howard
45cb9b4444 rp2/machine_pin: Fix simulated open drain with more than 32 GPIOs.
Changes are:
- Refactor the open-drain macros, add GPIO_ENABLE/DISABLE_OPEN_DRAIN, and
  move them to `mphalport.h`.
- Only use `uint64_t` for the open-drain mask if there are more than 32
  GPIOs (saves code size).
- Ensure we're shifting a `uint64_t` by using 1ULL constants.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-05-22 00:08:27 +10:00
Phil Howard
28c8fff6d8 rp2/machine_pin: Replace macros with Pico SDK functions.
Replace custom macros with Pico SDK functions, enabling support for RP2350B
variant chips with > 32 GPIOs.

Fixes issue #17241.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2025-05-22 00:03:20 +10:00
Angus Gratton
4545eb844d rp2: Disable the LWIP tick timer when not needed.
Prevents lightsleep being woken up every 64ms to service LWIP timers, when:

1. No netif is up, and
2. No TCP sockets are active

The TCP socket check may not be strictly necessary, but without ticking the
tcp timer they won't ever time out by themselves.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-21 13:47:45 +10:00
Damien George
a1ee42cd3e nrf: Use common implementation of machine disable/enable IRQ.
This is a breaking change due to the signature change of `enable_irq()`.
Previously the signature was:

    machine.enable_irq()

Now the signature matches other ports, and the docs, and is:

    machine.enable_irq(state)

Where `state` is the return value from `machine.disable_irq()`.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-21 13:30:40 +10:00
Damien George
cc7eb1a535 nrf/boards: Use 64 byte raw-paste buffer on PCA10028 and PCA10040.
To workaround issues with JLink CDC.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-21 13:14:42 +10:00
Damien George
e676b58d9f nrf: Fix UART write on parts that can't write more than 255 bytes.
Some MCUs cannot write more than 255 bytes to the UART at once.  Eg writing
256 bytes gets truncated to 0, writing 257 gets truncated to 1, etc.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-21 13:14:26 +10:00
Damien George
32c65ad455 nrf: Only process interrupt chars on UARTs used for REPL.
This commit adds an `attached_to_repl` property to each UART, and makes
sure that property is correctly set/unset when the UART is attached to or
detached from the REPL.

That property is then used to make sure incoming characters on the UART are
only checked for the interrupt character if the UART is attached to the
REPL.  Otherwise a board without REPL on UART can have its code interrupted
if ctrl-C is received on the UART.

Also, put incoming UART characters on to `stdin_ringbuf` instead of the
UARTs ring buffer (the former is much larger than the latter).

Signed-off-by: Damien George <damien@micropython.org>
2025-05-21 13:10:01 +10:00
Damien George
d5db8f0461 nrf: Use correct IRAM address for native code execution on nRF52.
On nRF52, the physical SRAM is mapped to 0x20000000 for data access and
0x00800000 for instruction access.  So, while native code is allocated and
written using addresses in the 0x20000000 range, it must execute from the
0x00800000 range.

This commit makes this work correctly on nRF52 MCUs by adjusting the
address.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-21 12:53:25 +10:00
Damien George
3d7edbd9ab py/persistentcode: Allow a port a custom commit function and track data.
Allows both MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA and MP_PLAT_COMMIT_EXEC
to be enabled at the same time.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-21 12:53:14 +10:00
Alessandro Gatti
3d19a8bc2d py/emitnative: Clean up int-indexed Viper load/store code.
This commit performs some minor clean up for the code involved in Viper
load/store operations when said operations have an integer index.

Most platform-specific code blocks were able to generate correct opcodes
even when the index is 0, but they would still fall back to the general
case.  The general case would still emit a shortened opcode sequence so
this commit does not alter the overall behaviour, but makes it easier to
extend platform-specific code whenever the full index range is going to
be handled rather than a subset of indices as it is now.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-21 02:02:09 +02:00
Alessandro Gatti
6b2792a097 py/asmthumb: Generate proper sequences for large register offsets.
This commit lets the Thumb native emitter generate a proper opcode
sequence when calculating an indexed register offset for load/store
operations with said offset beight both greater than 65535 and not
able to be represented as a shifted 8-bit bitmask.

The original code would assume the scaled index would always fit in 16
bits and silently discard upper bits of the offset.  Now an optimised
constant loading sequence is emitted instead, and the final offset is
also stored in the correct register in all cases.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-21 02:01:22 +02:00
Alessandro Gatti
2260fe0828 tests/micropython/viper_ptr: Add tests for arch edge cases.
This commit adds a series of test cases to exercise the Viper code
generator load/store emitting capabilities on certain boundary
conditions.

The new test cases check whether the emitted load/store code performs
correctly when dealing with specific memory offsets, which trigger
specific code generation sequences on different architectures.

Right now the cases are for unsigned offsets whose bitmasks span up to
5, 8, and 12 bits (respectively Arm/Thumb, Xtensa, RV32).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-21 02:00:40 +02:00
Alessandro Gatti
e66a6022e2 py/asm: Remove unused generic ASM API opcode definitions.
This commit removes the ASM_LOAD_REG_REG and ASM_STORE_REG_REG generic
ASM API opcodes from all backends, as they are not used anymore in the
native emitter framework.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-21 01:50:12 +02:00
Alessandro Gatti
b6d269ee32 py/emitnative: Refactor Viper register-indexed load/stores.
This commit cleans up the Viper code generation blocks for
register-indexed load and store operations.

An attempt is made to simplify the code in the common code generator
code block, by moving architecture-specific code to the appropriate
native generation backends whenever possible.  This should make that
specific bit of code in the Viper generator clearer and easier to
maintain in the long term.

To achieve this, six generic assembler meta-opcodes have been
introduced, named `ASM_{LOAD,STORE}{8,16,32}_REG_REG_REG`.  A
platform-independent implementation for those operations is provided, so
backends that cannot emit a shorter sequence for the requested operation
or are fine with the platform-independent implementation can just not
provide said meta-opcodes.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-21 01:50:12 +02:00
Alessandro Gatti
04c6b99cb9 py/emitnative: Improve Viper register-indexed code for Thumb.
This commit lets the Viper code generator use optimised code sequence
for register-indexed load and store operations when generating Thumb
code.

Register-indexed load and store operations for Thumb now can take at
most two machine opcodes for halfword and word values, and just a single
machine opcode for byte values.  The original implementation could
generate up to four opcodes in the worst case (dealing with word
values).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-21 01:50:11 +02:00
Alessandro Gatti
1d37caa367 py/emitnative: Improve Viper register-indexed code for Arm.
This commit lets the Viper code generator use optimised code sequences
for register-indexed load and store operations when generating Arm code.

The existing code defaulted to generic multi-operations code sequences
for Arm code on most cases.  Now optimised implementations are provided
for register-indexed loads and stores of all data sizes, taking at most
two machine opcodes for each operation.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-21 01:50:11 +02:00
Angus Gratton
186caf9f03 extmod/network_cyw43: Disconnect STA if making inactive.
esp32 port will disconnect if active(0) is called on a STA
interface, but rp2 port stays associated without this change.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-20 23:14:41 +10:00
Alessandro Gatti
9ef16b466b extmod/modjson: Detect unterminated composite entities.
This commit makes the JSON parser raise an exception when handling
objects or arrays whose declaration is incomplete, as in missing the
closing marker (brace or bracket) and if the missing marker would have
been the last non-whitespace character in the incoming string.

Since CPython's JSON parser would raise an exception in such a case,
unlike MicroPython's, this commit aligns MicroPython's behaviour with
CPython.

This commit fixes issue #17141.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-19 02:09:40 +02:00
Damien George
7a55cb6b36 tests/run-tests.py: Add list of passed/skipped tests to _result.json.
The output `_result.json` file generated by `run-tests.py` currently
contains a list of failed tests.  This commit adds to the output a list of
passed and skipped tests, and so now provides full information about which
tests were run and what their results were.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-18 00:31:48 +10:00
Jos Verlinde
e39243c382 docs/reference/mpremote: Document the 'fs tree' command.
Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
2025-05-18 00:20:46 +10:00
Jos Verlinde
d945316432 tools/mpremote/tests: Add tests for 'fs tree' command.
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
2025-05-18 00:20:43 +10:00
Jos Verlinde
1dfb5092fc tools/mpremote: Add new 'fs tree' command.
Add `mpremote fs tree` command to show a tree of the device's files.  It:
- Shows a treeview from current path or specified path.
- Uses the graph chars ("├── ", "└── ") (not configurable).
- Has the options:
    -v/--verbose adds the serial device name to the top of the tree
    -s/--size add a size to the files
    -h/--human add a human readable size to the files

Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
2025-05-18 00:19:14 +10:00
Elvis Pfutzenreuter
ecbbc512b2 esp32/network_lan: Add PHY_GENERIC device type.
Support the new PHY_GENERIC device type, added in ESP-IDF v5.4.0 [1].

This PHY driver was added to ESP-IDF to support "generic"/oddball PHY
LAN chips like the JL1101, which offer no features beyond the bare
802.3 PHY standard and don't actually need a chip-specific driver (see
discussion at [2]).

[1] 0738314308
[2] https://github.com/espressif/esp-eth-drivers/pull/28

Signed-off-by: Elvis Pfutzenreuter <epxx@epxx.co>
2025-05-16 15:34:20 -03:00
Rick Sorensen
90aeac800a esp32/machine_i2c: Fix default I2C pins for C3, S3.
The default I2C init does not require setting SCL or SDA but the default
I2C0 pins for C3, S3 conflict with the espressif GPIO usage.

For the C3, pins 18/19 are for USB/JTAG.  If used for I2C() they will cause
the REPL to hang on initialization of the I2C.

For the S3 pin 19 is allocated for USB/JTAG also but the defaults do not
seem to affect the REPL.

See related #16956.

Fixes issue #17103.

Signed-off-by: Rick Sorensen <rick.sorensen@gmail.com>
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-16 17:39:10 +10:00
Daniël van de Giessen
06d8c084b9 esp32/modesp32: Implement esp32.idf_task_info().
This adds a new function, `esp32.idf_task_info()`, that can be used to
retrieve task statistics which is useful for diagnosing issues where some
tasks are using up a lot of CPU time.

It's best used in conjunction with the `utop` module from micropython-lib.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-16 16:49:59 +10:00
Angus Gratton
10f6c0699e esp32/network_lan: Add support for LAN8670 PHY.
This adds support for LAN8670 to the esp32 port.  Enabled conditionally for
the esp32 target, if ESP-IDF version is new enough (v5.3 or newer).

Fixes issue #15731.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-16 15:16:06 +10:00
IhorNehrutsa
f48b981567 esp32: Update to use ESP-IDF v5.4.1.
This version of the IDF uses about 1KB more IRAM and 1KB more DRAM on most
boards, but 6.5KB more DRAM usage on the S3.  It seems that's due to a lot
of small increases in many components.

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
2025-05-16 14:02:39 +10:00
Damien George
e1ab04e820 esp32/mpthreadport: Fix double delete of tasks on soft reset.
Python threads (created via the `_thread` module) are backed by a FreeRTOS
task.  Managing the deletion of the task can be tricky, and there are
currently some bugs with this in the esp32 port.

The actual crash seen was in FreeRTOS' `uxListRemove()`, and that's because
of two calls to `vTaskDelete()` for the same task: one in
`freertos_entry()` when the task ran to completion, and the other in
`mp_thread_deinit()`.  The latter tried to delete the task a second time
because it was still in the linked list, because `vTaskPreDeletionHook()`
had not yet been called.  And the reason `vTaskPreDeletionHook()` was yet
to be called is because the FreeRTOS idle task was starved.

This commit fixes that.

There are three things done by this commit:
- remove the `vTaskPreDeletionHook`, it's not needed anymore because task
  stack memory is allocated by the IDF, not on the MicroPython heap
- when a task finishes it now removes itself from the linked list, just
  before it deletes itself
- on soft reset, all tasks are deleted and removed from the linked list in
  one swoop (while the mutex is held)

Signed-off-by: Damien George <damien@micropython.org>
2025-05-16 13:31:34 +10:00
IhorNehrutsa
9d565182d7 docs/esp32/quickref: Add PWM lightsleep example.
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
2025-05-16 12:37:25 +10:00
IhorNehrutsa
a724545193 esp32/mpconfigport: Document how to get more debug info.
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
2025-05-16 12:37:14 +10:00
IhorNehrutsa
150a5aa3a1 esp32/machine_pwm: Improve PWM and make its API match other ports.
This reduce inconsistencies between esp32 PWM and other ports:
1. duty_u16() high value is 2**16-1 == 65535
2. Invert PWM wave with invert=1 parameter
3. Enable PWM in light sleep mode
4. Allow PWM output and read pulse input simultaneously on the same Pin()
5. Code refactoring

Co-Authored-By: Angus Gratton <angus@redyak.com.au>
Co-Authored-By: robert-hh <robert@hammelrath.com>
Co-Authored-By: Andrew Leech <andrew.leech@planetinnovation.com.au>
Co-Authored-By: Yoann Darche <yoannd@hotmail.com>

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
2025-05-16 12:35:58 +10:00
IhorNehrutsa
c310301f27 docs/esp32: Improve PWM documentation and examples.
This reduces inconsitencies between esp32 and other ports.

According to the discussion in #10817.

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
2025-05-16 12:34:32 +10:00
Jeff Epler
6d74b4e3c1 tools/gen-cpydiff.py: Ensure every item has at least 2 TOC levels.
Previously, the navigation ended up messy when the (long) description of
the item became used as a 2nd level header, meaning that it was placed in
the navigation.  Check for this when generating cpydiff so that new cases
don't sneak in unnoticed.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-16 11:52:03 +10:00
Jeff Epler
ea19f3b735 tests/cpydiff: Ensure all have two levels of category.
This improves the TOC display of the generated differences section.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-16 11:52:03 +10:00
Jeff Epler
a19d3f742e tools/gen-cpydiff.py: Fix RST heading generation.
The heading character for the difference title was always "~", but items
had been added which had just a single heading level.  This made the
generated table of contents confused about heading levels, because heading
levels are not fixed in rst, but are inferred from the order they appear in
the document.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-16 11:52:03 +10:00
Jeff Epler
8648e6d1cf tests/cpydiff: Add test of underscore-in-literals.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-16 11:52:03 +10:00
Jeff Epler
605eda158d tools/gen-cpydiff.py: Improve stdout vs stderr interleaving.
In the syntax_space cpydiff, all the warnings were shown after the other
output.  This is because the output always showed all of stdout first and
all of stdout second.

By running Python in unbuffered mode and using `stderr=STDOUT`, the two
streams are interleaved in exactly the order they're printed, so the
SyntaxWarnings are interleaved with the other output.

By using the `encoding=` argument of Popen, the need to explicitly convert
to utf-8 is avoided.  The encoding of the input also becomes utf-8 in this
case, which all the test cases are (well, they're all ASCII, I think).  As
in `run-tests.py`, setting PYTHONIOENCODING ensures the Python
interpreter's input and output are in utf-8, which is not always the case,
especially on Windows systems.

I spot-checked the generated doc pages and they all seemed to make sense
still.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-16 11:52:03 +10:00
Jeff Epler
2f97d1dd28 tests/cpydiff: Document that uPy requires space after number+period.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-16 11:51:43 +10:00
Jeff Epler
e22c666d06 tests/cpydiff: Explain the numeric literal parsing difference.
Fixes issue #17224.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-16 11:45:18 +10:00
Damien George
44bcfe53de tests/extmod/vfs_lfs_error.py: Test value of all OSError's errno.
To make sure they have the correct value.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-15 13:09:49 +10:00
Damien George
62d26bfc15 extmod/vfs_lfsx: Fix errno value raised from chdir.
OSError errno values should be positive.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-15 13:09:49 +10:00
Daniël van de Giessen
4208970451 tools/verifygitlog.py: Allow long co-author and sign-off names.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-15 13:03:11 +10:00
Damien George
51b821ce82 tools/verifygitlog.py: Disallow a leading slash in commit subject line.
Signed-off-by: Damien George <damien@micropython.org>
2025-05-15 13:01:41 +10:00
Daniël van de Giessen
3b1e22c669 esp32/network_ppp: Restructure to match extmod/network_ppp_lwip.
The ESP32 PPP implementation predates the generic
implementation in extmod. The new extmod
implementation has a few advantages such as a
better deinitialisation procedure (the ESP32
implemementation would not clean up properly and
cause crashes if recreated) and using the UART IRQ
functionality instead of running a task to read
data from the UART.

This change restructures the ESP implementation to
be much closer to the new extmod version, while
also bringing a few tiny improvements from the
ESP32 version to the extmod version. The diff
between extmod/network_ppp_lwip.c and
ports/esp32/network_ppp.c is now a small set of
easy to review ESP32 port-specific changes.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-15 11:56:14 +10:00
Alessandro Gatti
2406582479 esp32/network_common: Raise a memory error on ESP_ERR_NO_MEM.
This commit changes the error handler for WiFi operations to recognise
out of memory conditions reported by ESP-IDF functions, and report them
as more descriptive exceptions rather than a generic "error 0x101".

The error handler only provided a human-readable error description for
WiFi-specific error codes (codes in the ESP_ERR_WIFI_BASE range), but
WiFi functions are known to return other codes.  Now ESP_ERR_NO_MEM is
covered with a specific error message, making it easier to debug issues
related to running out of ESP-IDF heap.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-15 11:29:41 +10:00
Daniël van de Giessen
155fa94fbf esp32/machine_uart: Correctly manage UART queue and event task.
If the driver was reinitialised while there was
already an event task running the queue that task
is trying to receive from would be deleted,
causing it to try to take a lock that no longer
existed and deadlocking the CPU.

This change ensures the task is always shut down
before recreating the queue and recreates the task
afterwards.

It also allows setting an IRQ handler before the
UART is initialized (like other ports allow),
removes the task when the UART is deinitialized
(which was previously missing), adds a check that
no event task can be started when no queue exists,
and adds a check to prevent reinitialising the
UART driver unnecessarily.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-14 15:55:31 +02:00
Alessandro Gatti
883dc41d46 esp32/main: Make the entry point function name configurable.
This commit introduces a new port configuration entry allowing the entry
point function name to be changed, from "app_main" to a custom name.

This is needed when MicroPython is embedded as an ESP-IDF component,
since the "app_main" symbol is already provided elsewhere, making
compilation not possible.  Marking MicroPython's symbol as weak would
make it compile and make it possible to create and start the MicroPython
task anyway with the right FreeRTOS task creation incantation, but it is
probably easier to just rename the initialisation function into
something else that can be accessed from outside.

When MicroPython is embedded as an ESP-IDF component, the
MICROPY_ESP_IDF_ENTRY definition can be set to indicate the new entry
point function name.  The new function name prototype should still be
defined in external code to let linking succeed.

Also, the NLR failure callback is marked as weak to give the chance of
handling such error in a more controlled fashion rather than trigger an
unconditional board restart.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-14 06:26:31 +02:00
Alessandro Gatti
116d0d4945 esp32/esp32_common.cmake: Allow adding defines and compiler flags.
This commit introduces two extra CMake variables, MICROPY_DEF_COMPONENT
and MICROPY_COMPILE_COMPONENT, that make it easier to integrate
MicroPython as a custom ESP-IDF component.

Whilst there is no official MicroPython component available for ESP-IDF,
integration can be achieved with some minor CMake scripting outside the
MicroPython tree - except for customisation of compilation defines and
build flags, which is what this commit tries to provide.

Compilation defines customisation is especially important for
MicroPython configuration, as it is not possible to inject a value for
MP_CONFIGFILE otherwise.  This means that unless MicroPython itself is
forked first to edit ports/esp32/mpconfigport.h, it is not possible to
perform any meaningful configuration of the interpreter/runtime when
included as a component.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-14 06:25:59 +02:00
robert-hh
1d4bf8ac40 esp32/machine_timer: Fix timer.value() for an uninitialized timer.
Raises a value error in that case, which happens after a timer was created
but not initialized, or after calling `timer.deinit()`.

Fixes issue #17033.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-14 11:58:36 +10:00
Alessandro Gatti
d7371124d2 esp32/esp32_common.cmake: Use the tinyusb source files from ESP-IDF.
This commit removes the explicit dependency on the vendored tinyusb
version for the ESP32S2 and ESP32S3 boards.

Tinyusb is still available to MicroPython through a dependency on the
`espressif/esp_tinyusb` ESP-IDF component, which in turn depends on
the `espressif/tinyusb` component itself.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-14 11:02:31 +10:00
Jeff Epler
f77fd6257c tests/cpydiff: Document format separator difference.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-13 12:19:46 +10:00
Jeff Epler
9032491efd py/objstr: Add support for the :_b/o/x specifier in str.format.
This groups non-decimal values by fours, such as bbb_bbbb_bbbb.  It also
supports `{:_d}` to use underscore for decimal numbers (grouped in threes).

Use of incorrect ":,b" is not diagnosed.

Thanks to @dpgeorge for the suggestion to reduce code size.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-05-13 12:16:35 +10:00
Alessandro Gatti
f47e214cdc all: Rename the "NORETURN" macro to "MP_NORETURN".
This commit renames the NORETURN macro, indicating to the compiler
that a function does not return, into MP_NORETURN to maintain the same
naming convention of other similar macros.

To maintain compaitiblity with existing code NORETURN is aliased to
MP_NORETURN, but it is also deprecated for MicroPython v2.

This changeset was created using a similar process to
decf8e6a8b ("all: Remove the "STATIC"
macro and just use "static" instead."), with no documentation or python
scripts to change to reflect the new macro name.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-05-13 10:36:47 +10:00
Angus Gratton
69993daa5c rp2/modmachine: Add mutual exclusion for machine.lightsleep().
There's no specified behaviour for what should happen if both CPUs call
`lightsleep()` together, but the latest changes could cause a permanent
hang due to a race in the timer cleanup code.  Add a flag to prevent hangs
if two threads accidentally lightsleep, at least.

This allows the new lightsleep test to pass on RPI_PICO and RPI_PICO2, and
even have much tighter time deltas.  However, the test still fails on
wireless boards where the lwIP tick wakes them up too frequently.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-12 16:30:46 +10:00
Angus Gratton
977fd94856 tests/ports/rp2: Add a test case for light sleeping from CPU1.
Not currently passing.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-12 16:30:38 +10:00
Peter Harper
03da15575f tests/ports/rp2: Update machine idle test to revert skip for RP2350.
This reverts commit b42bb911c6.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2025-05-12 16:29:51 +10:00
Peter Harper
2a4f1c9f0f rp2/modmachine: Add debug code for mp_machine_lightsleep.
Add some debug code that can be enabled to determine why lightsleep is
returning early.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2025-05-12 16:29:37 +10:00
Peter Harper
ee2c78cd97 rp2: Use pico-sdk alarm pool instead of soft timer for sleep.
Stop using soft timer for `mp_wfe_or_timeout`.  Now uses the alarm pool
again as issues with this code have been fixed.  This resolves the "sev"
issue that stops the RP2350 going idle.

Also, change the lightsleep code to use the hardware timer library and
alarm 1, as alarm 2 is used by and soft timers and alarm 3 is used by the
alarm pool.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2025-05-12 16:24:51 +10:00
Damien George
a05766f47b tests/multi_net: Add test that requires queuing UDP packets.
This commit adds a new network multi-test which sends a burst of UDP
packets from the client, and the server doesn't recv them until they have
all been sent.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-12 14:19:34 +10:00
Damien George
26e978e7bc extmod/modlwip: Implement a queue of incoming UDP/raw packets.
The bare-metal lwIP socket interface is currently quite limited when used
for UDP streams, because it only allows one outstanding incoming UDP
packet.  If one UDP packet is waiting to be socket.recv'd and another one
comes along, then the second one is simply dropped.

This commit implements a queue for incoming UDP and raw packets.  The queue
depth is fixed at compile time, and is currently 4.

This allows better use of UDP connections, eg more efficient.  It also
makes DTLS work better which sometimes has a queue of UDP packets (eg
during the connection phase).

Signed-off-by: Damien George <damien@micropython.org>
2025-05-12 14:17:44 +10:00
Damien George
61eedbbd11 tools/verifygitlog.py: Apply stricter rules on git subject line.
There is a bit of ambiguity as to how the prefix of the git subject line
should look like.  Eg `py/vm: ...` vs `py/vm.c: ...` (whether the extension
should be there or not).

This commit makes the existing CI check of the git commit message stricter,
by applying extra rules to the prefix, the bit before the : in the subject
line.  It now checks that the subject prefix:
- doesn't start with unwanted bits: ., /, ports/
- doesn't have an extension: .c, .h, .cpp, .js, .rst or .md

Full error messages are given when a rule does not pass.

This helps to reduce maintainer burden by applying stricter rules, to keep
the git commit history consistent.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-12 13:47:03 +10:00
Damien George
487c94c253 tests/extmod/vfs_rom.py: Clear sys.path before running test.
Otherwise if the target has certain files/directories (such as "test") in
its filesystem then these interfere with the unit tests.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-12 13:33:42 +10:00
Damien George
f7c53cd221 tests/net_inet: Update micropython.org certificate for SSL tests.
The Let's Encrypt root certificate has changed so needs updating in these
tests.

Also use `bytes.fromhex()` instead of `binascii.unhexlify()`, to eliminate
the need for the `binascii` module.  Both of these features are controlled
by `MICROPY_PY_BUILTINS_BYTES_HEX`, so the test will still work on the same
targets that it previously did.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-12 13:32:06 +10:00
Angus Gratton
ae6062a45a lib/littlefs: Fix string initializer in lfs1.c.
Avoids the new Wunterminated-string-literal when compiled with gcc 15.1.

It would be preferable to just disable this warning, but Clang
-Wunknown-warning-option kicks in even when disabling warnings so this
becomes fiddly to apply.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-09 18:31:40 +10:00
Angus Gratton
9f86005885 py/emitinlinethumb: Refactor string literal as array initializer.
Avoids the new Wunterminated-string-literal when compiled with gcc 15.1.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-09 18:31:40 +10:00
Angus Gratton
7d5aba0523 extmod/moductypes: Refactor string literal as array initializer.
Avoids the new Wunterminated-string-literal when compiled with gcc 15.1.

Also split out the duplicate string to a top-level array (probably the
duplicate string literal was interned, so unlikely to have any impact.)

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-09 18:31:40 +10:00
Angus Gratton
3fa77bdc7d rp2: Add temporary workaround for GCC 15.1 build failure.
This is a workaround for this upstream issue:
https://github.com/raspberrypi/pico-sdk/issues/2448

Can be removed after the next pico-sdk update.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-09 18:31:25 +10:00
Damien George
d01a981a9b py/mpconfig: Enable io.IOBase at core feature level.
IOBase is quite an important building block of other parts of the system,
such as `mpremote mount` and running .mpy and native tests.

This feature costs +244 bytes of firmware size on ARM Thumb2 architectures,
which is worth the cost for the extra features it enables.

The change here means that `io.IOBase` is now enabled on all nrf boards,
(previously it was only nRF52840 and nRF9160) and also B_L072Z_LRWAN1
(there is no change to other ports or boards).

Signed-off-by: Damien George <damien@micropython.org>
2025-05-09 12:43:27 +10:00
Damien George
9c8c219f8a rp2/rp2_dma: Fix default value used in pack_ctrl on RP2350.
The bit position of CHAIN_TO is not the same as on RP2040.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-09 12:05:04 +10:00
Damien George
928466d74c rp2/Makefile: Add deploy target that uses picotool load.
This is a convenient way to deploy firmware to an RP2xxx-based board.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-09 12:01:50 +10:00
Angus Gratton
d00eab4a30 rp2,extmod/cyw43: Move the LWIP responder fix into common CYW43 config.
This means the fix from dd1465e7 will also apply to stm32 and mimxrt ports
that use CYW43.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-08 15:32:05 +10:00
Angus Gratton
b2cda6c604 extmod,alif,mimxrt,rp2,stm32: Create common cyw43 driver config header.
This is only a surface level refactor, some deeper refactoring would be
possible with (for example) the SDIO interface in mimxrt and stm32, or the
BTHCI interface which is is similar on supported ports. But sticking to
cases where the macros are the same across all ports.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-08 15:32:05 +10:00
Anton Blanchard
45e4deb96d zephyr/mpconfigport: Fix mp_int_t and mp_uint_t to work on 64-bit archs.
These both need to fit a pointer, so make them `intptr_t` and `uintptr_t`,
similar to other ports.

Signed-off-by: Anton Blanchard <antonb@tenstorrent.com>
2025-05-07 21:36:54 +10:00
danicampora
fe28cd78fe zephyr/modbluetooth_zephyr: Allow BLE to create services at runtime.
This commit adds the required functionality for a peripheral to create
services at runtime, using `BLE.register_services()`.

The feature is enabled on the nrf52840dk_nrf52840 board.

Note that the `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n` option must be used
so that BLE notifications/indications can be sent even if not subscribed.

Signed-off-by: danicampora <danicampora@gmail.com>
2025-05-07 21:25:53 +10:00
Jos Verlinde
1b123579a2 py/makeversionhdr.py: Change utcfromtimestamp() to fromtimestamp().
The former is deprecated.

Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
2025-05-07 17:31:11 +10:00
Daniël van de Giessen
aedaa40595 py/modthread: Initialize thread state nlr_top to NULL.
This ensures the check in MP_NLR_JUMP_HEAD works as expected and
nlr_jump_fail gets called so we get a bit better error message.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-07 17:25:43 +10:00
Daniël van de Giessen
2b29b1b8f9 lib/littlefs: Reuse existing CRC32 function to save space.
Getting this to work required fixing a small issue in `lfs2_util.h`, which
has been submitted upstream.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-07 17:03:28 +10:00
Daniël van de Giessen
9287a1e6ea lib/littlefs: Update LittleFS to v2.10.2.
Going above the root directory (/../foo) now gives an error.  This is an
intentional change made by LittleFS.  It required a update of the testsuite
and is a (minor) compatibility break.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2025-05-07 17:01:16 +10:00
robert-hh
80d03b7780 samd/samd_qspiflash: Remove the attempt to handle a unknown device.
Since all QSPI flash device used by this port are defined, this code was
only used unintentionally.  Besides that it was incomplete, so better drop
it.

Note: The flash type for Mini-SAM had to be changed too.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-07 16:20:19 +10:00
robert-hh
2e6df08e05 samd/samd_spiflash: Improve the flash type detection.
Changes in this commit:
- Check for the proper SFDP header.
- Use the flash size information from SFDP, if present.
- Add two more special flash chips <= 1 MByte without SFDP.  JEDEC-ID table
  for special flash types instead of a series of conditional statements.
- Add a compile flag `MICROPY_HW_SPIFLASH_SIZE` to set the size in
  `mpconfigboard.h`, which replaces getting the size from the JEDEC ID or
  the SFDP record.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-07 16:19:48 +10:00
robert-hh
c22c2c8066 samd/boards/SAMD_GENERIC_D51xxx: Fix VFS settings for internal flash.
Fixes in this commit:
- The wrong loader script was assigned for SAMD_GENERIC_D51X20, causing the
  VFS block count to be wrong.
- Change the VFS block size from 1536 to 2048.  With the setting of 1536,
  writing more that 1536 bytes at once failed.  This applies to
  SAMD_GENERIC_D51X19 and SAMD_GENERIC_D51X20.  No other SAMD51 board uses
  the internal flash for the file system.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-07 16:18:07 +10:00
robert-hh
ff9e01782b samd/modtime: Change time.time_ns() to follow the RTC time.
That is done by adding the offset to epoch, following the scheme from the
RP2 port.  RTC and `ticks_us()` are not precisely in sync, and so the
difference between `time.time_ns()/1e9` and `time.time()` will increase by
more than 9 seconds/24h.  So applications should avoid using `time.time()`
and `time.time_ns()` in the same context.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-07 16:17:07 +10:00
robert-hh
2fda4bbe05 samd/machine_i2c: Add the timeout keyword argument to the constructor.
To make it compliant with the documentation.  The default value is 50000us.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-07 16:16:45 +10:00
robert-hh
8e328da9bf samd/boards/SAMD_GENERIC_Dxxx: Add Microchip URL to board.json.
To the Microchip Web site.  Thanks to Matt Trentini for suggesting this
site.

Signed-off-by: robert-hh <robert@hammelrath.com>
2025-05-07 16:16:11 +10:00
Malcolm McKellips
288dce26bd docs,ports: Fix SparkFun capitalization.
This is a follow-up to 1e92bdd206 correcting
more of the instances where "Sparkfun" should be "SparkFun".

Signed-off-by: Damien George <damien@micropython.org>
2025-05-07 15:16:55 +10:00
Yoctopuce dev
bdb7e036d2 extmod/asyncio: Fix early exit of asyncio scheduler.
This commit fixes three open issues related to the asyncio scheduler
exiting prematurely when the main task queue is empty, in cases where
CPython would not exit (for example, because the main task is not done
because it's on a different queue).

In the first case, the scheduler exits because running a task via
`run_until_complete` did not schedule any dependent tasks.

In the other two cases, the scheduler exits because the tasks are queued in
an event queue.

Tests have been added which reproduce the original issues.  These test
cases document the unauthorized use of `Event.set()` from a soft IRQ, and
are skipped in unsupported environments (webassembly and native emitter).

Fixes issues #16759, #16569 and #16318.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-05-07 14:56:47 +10:00
Angus Gratton
79abdad9e9 tests/extmod: Rename ssl tests that only use the tls module.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-02 17:24:58 +10:00
Angus Gratton
70ed315193 py/malloc: Add mutex for tracked allocations.
Fixes thread safety issue that could cause memory corruption on ports
with (MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL) - currently only rp2 and
unix have this configuration.

Adds unit test for TLS sockets that exercises this code path.  I wasn't
able to make this fail on rp2, the race condition window is pretty narrow
and may not have a direct impact on a quiet system.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-05-02 17:24:16 +10:00
Ayush Singh
bee1fd5e78 zephyr/boards: Enable ADC on beagleconnect_freedom.
Enable Analog inputs.  Requires Zephyr >= v3.8.0.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2025-05-02 12:39:16 +10:00
Vdragon
ced7ebb873 docs/zephyr: Add zephyr FlashArea IDs docs.
Signed-off-by: Vdragon <mail@massdriver.space>
2025-05-02 12:37:45 +10:00
Vdragon
8728db3e41 zephyr: Introduce auto-listing of FlashArea Partitions.
This enables listing all flash area partitions automagically instead of
just sotrage_partitions.  It uses the label, and the ID when not present.

Signed-off-by: Vdragon <mail@massdriver.space>
2025-05-02 12:37:20 +10:00
Vdragon
6601d4d7eb zephyr: Create ability to use device_next with CDC ACM as REPL.
This enables using the newer USB stack and its CDC ACM for the REPL.

To switch to it, board file must contain `CONFIG_USB_DEVICE_STACK_NEXT=y`
and `CONFIG_USBD_CDC_ACM_CLASS=y`.  In the case of a board that is a
platform that supports the older device stack, `CONFIG_USB_DEVICE_STACK=n`
may be necessary.

Signed-off-by: Vdragon <mail@massdriver.space>
2025-05-02 12:27:14 +10:00
Damien George
e53f262a85 tools/mpremote: For mip install, use hash to skip files that exist.
When using `mip install`, if a file that needs to be downloaded already
exists locally, then the hash of that local file will be computed and if it
matches the known hash of the remote file it will not be downloaded.

Hashes in mip are guaranteed unique, so this change should never leave
stale files on the filesystem.

This behaviour follows that of the `mip` package in `micropython-lib`.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-02 11:44:32 +10:00
Damien George
4117a2d9b5 tools/ci.sh: Update URL for xtensa-lx106-elf-standalone.tar.gz.
The https://github.com/jepler/esp-open-sdk repository has been removed, so
use the file hosted at micropython.org (it's the same file).

Signed-off-by: Damien George <damien@micropython.org>
2025-05-02 11:39:49 +10:00
Damien George
00a0cd70f5 tests/ports/rp2: Tune rp2.DMA test so it runs in all configurations.
Changes in this commit:
- Allow the DMA instance to be any instance, not just DMA(0); eg WLAN may
  be using DMA(0).
- Make the DMA timing test run a little faster by preloading `dma.active`.
- Run the DMA timing test 10 times and take the average time taken as the
  test result, to eliminate any big effects of caching.
- Change the expected time to `range(30, 80)` to cover RP2040, RP2350,
  RISC-V variants, and both bytecode and native emitter.
- Add a `sleep_ms(1)` after waiting for the IRQ to fire, so that any
  scheduled code gets a chance to run when the test is compiled with the
  native emitter.

With these changes this test passes reliably on RPI_PICO, RPI_PICO_W,
RPI_PICO2, RPI_PICO2_W, RPI_PICO2-RISCV and RPI_PICO2_W-RISCV, in both
bytecode and native emitter mode, with and without WLAN enabled.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-01 13:18:28 +10:00
Damien George
ffd7e0e28d tests/ports/rp2: Convert rp2.DMA test to a unittest.
This test is rather complicated and benefits from being a unittest.

Signed-off-by: Damien George <damien@micropython.org>
2025-05-01 13:18:28 +10:00
Damien George
3f1df4bacb tests/net_hosted: Only run network loopback test on supported targets.
Only a few ports have TCP/IP loopback enabled in their network stack, and
this test will only pass on those ports.  There's not really any good way
to do a feature check for loopback mode without actually running the test
and seeing if it passes/fails, so add an explicit check that the test is
running on a port known to support loopback.

(Enabling loopback on lwIP, eg RPI_PICO_W, costs +568 code and +272 bss and
is a rarely used feature, so not worth unconditionally enabling.)

Signed-off-by: Damien George <damien@micropython.org>
2025-05-01 11:16:29 +10:00
Patrick Joy
62479f2cb6 zephyr/boards: Add nrf9151dk board configuration.
Add support for the nrf9151dk.  This DK has a GD25WB256 32mb external QSPI
flash chip.

Signed-off-by: Patrick Joy <patrick@thinktransit.com.au>
2025-04-30 12:44:12 +10:00
Patrick Joy
e3d9d8ef51 zephyr/boards: Add nrf5340dk board configuration.
Add support for the nrf5340dk.  This DK has a MX25R64 8mb external QSPI
flash chip.

Compile using:

    $ west build -b nrf5340dk/nrf5340/cpuapp

Signed-off-by: Patrick Joy <patrick@thinktransit.com.au>
2025-04-30 12:29:11 +10:00
Vdragon
d939511dae zephyr: Create options to enable frozen modules.
Enables the ability to use frozen modules in the zephyr port.

Enabled by adding `CONFIG_MICROPY_FROZEN_MODULES` to the board
configuration file.  Manually set manifest path with
`CONFIG_MICROPY_FROZEN_MANIFEST`.

Signed-off-by: Vdragon <mail@massdriver.space>
2025-04-30 11:59:17 +10:00
Ayush Singh
f9a755c91c zephyr/boards: Enable PWM on beagleconnect_freedom.
Enable PWM config for bcf.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2025-04-30 00:30:27 +10:00
Ayush Singh
c9c39b88af docs/zephyr: Add quick reference for PWM support.
Add docs for PWM support.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2025-04-30 00:29:55 +10:00
Ayush Singh
f4a7e713ea zephyr/machine_pwm: Implement PWM support.
Implement PWM support using standard zephyr APIs, exposed as the standard
MicroPython `machine.PWM` class.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2025-04-30 00:28:45 +10:00
Maureen Helm
3c8d1b13f5 zephyr: Upgrade to Zephyr v4.0.0.
Updates the Zephyr port build instructions. The CI is updated to use
Zephyr docker image 0.27.4, SDK 0.17.0 and the latest Zephyr release
tag.

Tested on max32690fthr and frdm_k64f.

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
Signed-off-by: Detlev Zundel <dzu@member.fsf.org>
2025-04-29 23:00:37 +10:00
Detlev Zundel
b83606fe33 zephyr: Remove reference to CONFIG_MMC_VOLUME_NAME for v4.0.
Commit 07a8e3253a2d8a2076c9c83c4ed4158fa3fbb2a2 removes
CONFIG_MMC_VOLUME_NAME from the Kconfig space. Instead we need to use
the device tree to find the "disk-name" property of "zephyr,mmc-disk"
devices.

Signed-off-by: Detlev Zundel <dzu@member.fsf.org>
2025-04-29 23:00:37 +10:00
Detlev Zundel
cd3eaad05c zephyr: Fix call to thread_analyzer_print for v4.0.
Commit 1b6e0f64796dfd6f86a8679ea6d24e1fca1e63a8 for Zephyr v4.0.0
changed the function "thread_analyzer_print" to require a cpu argument
and allow thread analysis on each cpu separately. The argument is
ignored when THREAD_ANALYZER_AUTO_SEPARATE_CORES=n which is the
default on single core machines.

Promote this change to the MicroPython zephyr module.

Signed-off-by: Detlev Zundel <dzu@member.fsf.org>
Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2025-04-29 23:00:37 +10:00
Detlev Zundel
cd71db0172 zephyr: Fix prj.conf for v4.1-rc1.
The (deprecated) kconfig option NET_SOCKETS_POSIX_NAMES was removed in
commit abad505bdeed6102061767f45acd63323973f564 so remove it from our
configuration.

As the option has been deprecated longer, this also works for v3.7 and
v4.0 the other still supported versions.

Signed-off-by: Detlev Zundel <dzu@member.fsf.org>
2025-04-29 23:00:37 +10:00
Jos Verlinde
6406afb1f3 tools/mpremote: Prevent deletion of /remote files via rm -r.
Removes the risk of inadvertently deleting files on the host by preventing
the deletion of files via `rm -r` on the `/remote` vfs mount point.

Fixes issue #17147.

Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
2025-04-26 16:07:44 +10:00
Jos Verlinde
37fe3f66c3 tools/mpremote/tests: Add test for rm -r on /remote vfs.
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
2025-04-26 16:07:40 +10:00
Anson Mansfield
dc46cf15c1 tools/mpremote: Fix possibly-missing EOPNOTSUPP errno name.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-04-26 15:51:49 +10:00
Anson Mansfield
805fe083a3 tools/mpremote: Refactor error handling to apply generally to any errno.
This rewrites the code that previously manually emitted and caught various
OSError subclasses with equivalent code that uses the errno name dictionary
to do this generically, and updates the exception handler in do_filesystem
to catch them in a similarly-generic fashion using os.strerror to retrieve
an appropriate error message text equivalent to the current messages.

Note that in the CPython environments where mpremote runs, the call to the
OSError constructor already returns an instance of the corresponding mapped
exception subtype.

Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-04-26 15:50:00 +10:00
Anson Mansfield
cee0419021 tools/mpremote/tests: Add tests for errno behavior.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
2025-04-26 15:49:48 +10:00
stijn
9a377801dc unix/coveragecpp: Verify struct-initializing macros' C++-compatibility.
Add code using all relevant macros to make sure they initialize
structs correctly.

Signed-off-by: stijn <stijn@ignitron.net>
2025-04-24 15:55:06 +02:00
stijn
02eea0da24 py: Make struct-initializing macros compatible with C++.
This requires explicitly naming and initializing all members so add that
where needed and possible.  For MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1
this would require initializing the .callback member, but that's a bit
of a waste since the macro is always followed by a call to
nlr_push_jump_callback() to initialize exactly that member, so rewrite
the macro without initializers.

Signed-off-by: stijn <stijn@ignitron.net>
2025-04-24 15:55:06 +02:00
Damien George
076e07197e lib/lwip: Update lwIP to STABLE-2_2_1_RELEASE.
This updates lwIP from STABLE-2_2_0_RELEASE, which was released in
September 2023.  The latest STABLE-2_2_1_RELEASE was released in February
2025.

Signed-off-by: Damien George <damien@micropython.org>
2025-04-24 23:01:16 +10:00
Damien George
dcca3ff602 tools/mpremote: Use zlib.compressobj instead of zlib.compress.
Because the `wbits` parameter was only added to `zlib.compress` in
CPython 3.11.  Using `zlib.compressobj` makes the code compatible with much
older CPython versions.

Fixes issue #17140.

Signed-off-by: Damien George <damien@micropython.org>
2025-04-24 22:33:05 +10:00
Angus Gratton
584fa8800b esp32/tools: Update metrics_esp32 script for ESP-IDF >=v5.4.x.
The output of 'idf.py size' has changed, plus some other cleanups around
build dir name, etc.  Can now run on v5.2.2 and v5.4.1, probably other
versions.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-04-24 22:16:32 +10:00
Alessandro Gatti
ce7f65f967 tests/extmod/vfs_posix.py: Fix test on Android.
This commit makes a slight change to the vfs_posix test suite to let it
pass on Android.

On Android, non-root processes can perform most filesystem operations
only on a restricted set of directories.  The vfs_posix test suite
attempted to enumerate the filesystem root directory, and said directory
happens to be restricted for non-root processes.  This would raise
an EACCES OSError and terminate the test with a unexpected failure.

To fix this, rather than enumerating the filesystem root directory the
enumeration target is the internal shared storage area root - which
doesn't have enumeration restrictions for non-root processes.  The path
is hardcoded because it is guaranteed to be there on pretty much any
recent-ish device for now (it stayed the same for more than a decade for
compatibility reasons).  The proper way would be to query the storage
subsystem via a JNI round-trip call, but this introduces too much
complexity for something that is unlikely to break going forward.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-04-24 22:11:42 +10:00
Damien George
898c04ae0e tests/extmod/vfs_mountinfo.py: Don't import unused errno module.
Signed-off-by: Damien George <damien@micropython.org>
2025-04-24 22:06:11 +10:00
Damien George
a081b2e151 tests/extmod/vfs_lfs_ilistdir_del.py: Skip test if not enough memory.
Signed-off-by: Damien George <damien@micropython.org>
2025-04-24 22:06:11 +10:00
Damien George
c83e907d9d tests/extmod: Skip binascii tests when hexlify/unhexlify don't exist.
These functions are only available when `MICROPY_PY_BUILTINS_BYTES_HEX` is
enabled.

Signed-off-by: Damien George <damien@micropython.org>
2025-04-24 22:06:11 +10:00
Angus Gratton
f5cb9eb974 top: Bump Ruff version to v0.11.6.
Brings it into sync with a matching change to micropython-lib (which was
much older).  Includes one small automatic fix.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-04-24 21:42:21 +10:00
iabdalkader
0b72962336 drivers/cyw43: Remove old BTHCI UART backend.
It has been completely replaced by equivalent code in cyw43-driver.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-22 12:50:36 +10:00
iabdalkader
0f360880aa stm32/cyw43_configport: Update cyw43 config to use new BTHCI UART.
Update the cyw43 configuration to use the new BTHCI UART backend provided
by cyw43-driver.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-22 12:50:22 +10:00
iabdalkader
3bbed952fd mimxrt/cyw43_configport: Update cyw43 config to use new BTHCI UART.
Update the cyw43 configuration to use the new BTHCI UART backend provided
by cyw43-driver.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-22 12:49:14 +10:00
iabdalkader
399c10dc28 mimxrt/machine_uart: Enable CTS SION so it can be read.
The new CYW43 BTHCI UART backend requires CTS pin to be defined and
readable.  This patch enables the CTS pin SION bit to allow it to be read
regardless of mux mode.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-22 12:39:01 +10:00
iabdalkader
fa76d52edb drivers/ninaw10: Rename Bluetooth HCI backend driver.
Rename `bt_hci` to `bthci_uart` for consistency with the CYW43 driver and
to distinguish it from HCI backends that use a different transport.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-22 12:30:22 +10:00
iabdalkader
193460d18f drivers/esp-hosted: Rename Bluetooth HCI backend driver.
Rename `bthci` to `bthci_uart` for consistency with the CYW43 driver and to
distinguish it from HCI backends that use a different transport.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-22 12:30:18 +10:00
Alessandro Gatti
e3c2cf7a04 esp32/esp32_common.cmake: Skip BTree module when requested.
This commit makes the BTree module truly optional, as it was
unconditionally enabled in the shared CMake script for the port.

This meant that if a board/variant did explicitly turn BTree off said
request was not honoured by the build system and the BTree module would
still be brought in.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-04-22 12:18:04 +10:00
Damien George
048ccccee0 rp2: Enable compressed error messages by default.
Reduces firmware size by about 3000 bytes.

Signed-off-by: Damien George <damien@micropython.org>
2025-04-22 11:57:39 +10:00
Damien George
bfe16ef09b esp32: Enable compressed error messages by default.
Reduces firmware size by about 3300 bytes.

Signed-off-by: Damien George <damien@micropython.org>
2025-04-22 11:57:26 +10:00
Damien George
bb1489965f py/mkrules.cmake: Add CMake support for compressed error messages.
Signed-off-by: Damien George <damien@micropython.org>
2025-04-22 11:55:39 +10:00
Andrew Leech
d6c673f28f stm32/main: Replace mp_stack_set calls with new mp_cstack_init_with_top.
Required in MICROPY_PREVIEW_VERSION_2.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-04-22 11:29:48 +10:00
Andrew Leech
569d472bc7 extmod/modbluetooth: Use newer mp_map_slot_is_filled function.
Required in MICROPY_PREVIEW_VERSION_2.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-04-22 11:29:43 +10:00
Andrew Leech
9bde197004 rp2: Add exception text wrappers.
Required in MICROPY_PREVIEW_VERSION_2.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-04-22 11:29:36 +10:00
Andrew Leech
b6dbc47664 extmod/machine_usb_device: Add exception text wrappers.
Required in MICROPY_PREVIEW_VERSION_2.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-04-22 11:29:32 +10:00
Andrew Leech
7c7a9bdb34 drivers/ninaw10/machine_pin_nina: Add exception text wrappers.
Required in MICROPY_PREVIEW_VERSION_2.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2025-04-22 11:29:26 +10:00
dubiousjim
ba4179bb66 py/dynruntime.mk: Fix use of musl's libm.a when LINK_RUNTIME=1.
Like PICOLIBC, MUSL also has its math functions in libc.a.  There is a
libm.a, but it's empty.

Signed-off-by: dubiousjim <dubiousjim@gmail.com>
2025-04-22 11:12:13 +10:00
Angus Gratton
27f4351f5f CODECONVENTIONS: Document the static naming conventions.
Goal is to document what's most commonly already in use, not to come up
with a new standard.

Also reformat the doc a bit for easier deep linking.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-04-22 11:06:04 +10:00
Alessandro Gatti
38a3873310 unix/mpthreadport: Work around lack of thread cancellation on Android.
This commit fixes thread-related compilation issues under Android using
Termux as its runtime environment.

On Android's libc (Bionic) thread cancellation is not implemented, but
the Unix port uses that mechanism to provide asynchronous thread
termination.  In this commit there is a workaround for that, by adding a
new signal handler to each newly created thread, whose callback simply
exits the thread.  Threads are then sent the new signal rather than
being explicitly cancelled, which in turn trigger the signal handler to
stop the thread execution at the next possible occasion.

This makes the cancellation behaviour differ slightly on Android, as
threads are probably going to linger a little bit more since the method
introduced in this commit is equivalent to setting
PTHREAD_CANCEL_DEFERRED as the thread cancellation type.  On the other
hand there are no guarantees of immediate cancellation using
PTHREAD_CANCEL_ASYNCHRONOUS either.

This fixes the pthread-related issues reported in #16259.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-04-22 10:19:20 +10:00
David Yang
6025b78d01 unix/main: Remove PATH_MAX from realpath.
POSIX.1-2008 ensures realpath() give a dynamically allocated buffer if
NULL is passed (which is also true for ports/windows/realpath.c),
avoiding an explicit call to malloc() and use of PATH_MAX, which may be
undefined on some systems.

Signed-off-by: David Yang <mmyangfl@gmail.com>
2025-04-22 00:20:47 +08:00
Yoctopuce dev
52ca826880 unix/variants: Enable os.uname() in coverage build for tests.
In order to provide test coverage for the previous commit, `os.uname()`
support is added to the unix coverage build.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-04-21 17:38:42 +10:00
Yoctopuce dev
0d2c18c299 py/objstr: Fix handling of OP_MODULO with namedtuple.
This fix handles attrtuple as well, eg. os.uname().  A test case has been
added in basics/attrtuple2.py.

Fixes issue #16969.

Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
2025-04-21 17:37:39 +10:00
Jeff Epler
8faa6bafdc py/objrange: Match CPython range slicing.
The "index fixing" behavior of get_fast_slice_indexes are not desired here;
the underlying behavior of mp_obj_slice_indexes actually is.

Fixes issue #17016.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-04-21 17:09:37 +10:00
Jeff Epler
760b962924 tests/basics/builtin_range.py: Add more tests for range slicing.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-04-21 17:09:37 +10:00
Damien George
28901b2c30 all: Bump version to 1.26.0-preview.
Signed-off-by: Damien George <damien@micropython.org>
2025-04-21 17:07:30 +10:00
882 changed files with 24988 additions and 6218 deletions

View File

@@ -5,6 +5,8 @@ on:
pull_request:
paths:
- docs/**
- py/**
- tests/cpydiff/**
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -19,5 +21,7 @@ jobs:
- uses: actions/setup-python@v5
- name: Install Python packages
run: pip install -r docs/requirements.txt
- name: Build unix port
run: source tools/ci.sh && ci_unix_build_helper
- name: Build docs
run: make -C docs/ html

View File

@@ -25,6 +25,7 @@ jobs:
ci_func: # names are functions in ci.sh
- esp32_build_cmod_spiram_s2
- esp32_build_s3_c3
- esp32_build_c2_c6
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

View File

@@ -20,13 +20,20 @@ concurrency:
jobs:
build_and_test_arm:
strategy:
fail-fast: false
matrix:
ci_func: # names are functions in ci.sh
- bigendian
- sabrelite
- thumb
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_qemu_setup_arm
- name: Build and run test suite
run: source tools/ci.sh && ci_qemu_build_arm
- name: Build and run test suite ci_qemu_build_arm_${{ matrix.ci_func }}
run: source tools/ci.sh && ci_qemu_build_arm_${{ matrix.ci_func }}
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@@ -71,6 +71,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
with:
python-version: '3.11'
- name: Install packages
run: source tools/ci.sh && ci_unix_coverage_setup
- name: Build
@@ -129,6 +134,20 @@ jobs:
if: failure()
run: tests/run-tests.py --print-failures
longlong:
runs-on: ubuntu-22.04 # use 22.04 to get python2, and libffi-dev:i386
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_32bit_setup
- name: Build
run: source tools/ci.sh && ci_unix_longlong_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_longlong_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
float:
runs-on: ubuntu-latest
steps:
@@ -141,6 +160,18 @@ jobs:
if: failure()
run: tests/run-tests.py --print-failures
gil_enabled:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_gil_enabled_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_gil_enabled_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
stackless_clang:
runs-on: ubuntu-latest
steps:
@@ -169,23 +200,6 @@ jobs:
if: failure()
run: tests/run-tests.py --print-failures
settrace:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
with:
python-version: '3.11'
- name: Build
run: source tools/ci.sh && ci_unix_settrace_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_settrace_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
settrace_stackless:
runs-on: ubuntu-latest
steps:
@@ -262,3 +276,53 @@ jobs:
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
sanitize_address:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
with:
python-version: '3.11'
- name: Install packages
run: source tools/ci.sh && ci_unix_coverage_setup
- name: Build
run: source tools/ci.sh && ci_unix_sanitize_address_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_sanitize_address_run_tests
- name: Test merging .mpy files
run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests
- name: Build native mpy modules
run: source tools/ci.sh && ci_native_mpy_modules_build
- name: Test importing .mpy generated by mpy_ld.py
run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
sanitize_undefined:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
# Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
# Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
with:
python-version: '3.11'
- name: Install packages
run: source tools/ci.sh && ci_unix_coverage_setup
- name: Build
run: source tools/ci.sh && ci_unix_sanitize_undefined_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_sanitize_undefined_run_tests
- name: Test merging .mpy files
run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests
- name: Build native mpy modules
run: source tools/ci.sh && ci_native_mpy_modules_build
- name: Test importing .mpy generated by mpy_ld.py
run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@@ -28,13 +28,10 @@ jobs:
visualstudio: ['2017', '2019', '2022']
include:
- visualstudio: '2017'
runner: windows-latest
vs_version: '[15, 16)'
- visualstudio: '2019'
runner: windows-2019
vs_version: '[16, 17)'
- visualstudio: '2022'
runner: windows-2022
vs_version: '[17, 18)'
# trim down the number of jobs in the matrix
exclude:
@@ -42,9 +39,9 @@ jobs:
configuration: Debug
- visualstudio: '2019'
configuration: Debug
runs-on: windows-latest
env:
CI_BUILD_CONFIGURATION: ${{ matrix.configuration }}
runs-on: ${{ matrix.runner }}
steps:
- name: Install Visual Studio 2017
if: matrix.visualstudio == '2017'
@@ -52,13 +49,15 @@ jobs:
choco install visualstudio2017buildtools
choco install visualstudio2017-workload-vctools
choco install windows-sdk-8.1
- name: Install Visual Studio 2019
if: matrix.visualstudio == '2019'
run: |
choco install visualstudio2019buildtools
choco install visualstudio2019-workload-vctools
choco install windows-sdk-8.1
- uses: microsoft/setup-msbuild@v2
with:
vs-version: ${{ matrix.vs_version }}
- uses: actions/setup-python@v5
if: matrix.runner == 'windows-2019'
with:
python-version: '3.9'
- uses: actions/checkout@v4
- name: Build mpy-cross.exe
run: msbuild mpy-cross\mpy-cross.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }}
@@ -103,7 +102,7 @@ jobs:
env: i686
- sys: mingw64
env: x86_64
runs-on: windows-2022
runs-on: windows-latest
env:
CHERE_INVOKING: enabled_from_arguments
defaults:

View File

@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ruff version should be kept in sync with .pre-commit-config.yaml
- run: pipx install ruff==0.9.6
# ruff version should be kept in sync with .pre-commit-config.yaml & also micropython-lib
- run: pipx install ruff==0.11.6
- run: ruff check --output-format=github .
- run: ruff format --diff .

View File

@@ -12,8 +12,8 @@ repos:
verbose: true
stages: [commit-msg]
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Version should be kept in sync with .github/workflows/ruff.yml
rev: v0.9.6
# Version should be kept in sync with .github/workflows/ruff.yml & also micropython-lib
rev: v0.11.6
hooks:
- id: ruff
- id: ruff-format

View File

@@ -206,14 +206,21 @@ adhere to the existing style and use `tools/codeformat.py` to check any changes.
The main conventions, and things not enforceable via the auto-formatter, are
described below.
White space:
As the MicroPython code base is over ten years old, not every source file
conforms fully to these conventions. If making small changes to existing code,
then it's usually acceptable to follow the existing code's style. New code or
major changes should follow the conventions described here.
## White space
- Expand tabs to 4 spaces.
- Don't leave trailing whitespace at the end of a line.
- For control blocks (if, for, while), put 1 space between the
keyword and the opening parenthesis.
- Put 1 space after a comma, and 1 space around operators.
Braces:
## Braces
- Use braces for all blocks, even no-line and single-line pieces of
code.
- Put opening braces on the end of the line it belongs to, not on
@@ -221,18 +228,43 @@ Braces:
- For else-statements, put the else on the same line as the previous
closing brace.
Header files:
## Header files
- Header files should be protected from multiple inclusion with #if
directives. See an existing header for naming convention.
Names:
## Names
- Use underscore_case, not camelCase for all names.
- Use CAPS_WITH_UNDERSCORE for enums and macros.
- When defining a type use underscore_case and put '_t' after it.
Integer types: MicroPython runs on 16, 32, and 64 bit machines, so it's
important to use the correctly-sized (and signed) integer types. The
general guidelines are:
### Public names (declared in headers)
- MicroPython-specific names (especially any declared in `py/` and `extmod/`
directories) should generally start with `mp_` or `MP_`.
- Functions and variables declared in a header should generally share a longer
common prefix. Usually the prefix matches the file name (i.e. items defined in
`py/obj.c` are declared in `py/obj.h` and should be prefixed `mp_obj_`). There
are exceptions, for example where one header file contains declarations
implemented in multiple source files for expediency.
### Private names (specific to a single .c file)
- For static functions and variables exposed to Python (i.e. a static C function
that is wrapped in `MP_DEFINE_CONST_FUN_...` and attached to a module), use
the file-level shared common prefix, i.e. name them as if the function or
variable was not static.
- Other static definitions in source files (i.e. functions or variables defined
in a .c file that are only used within that .c file) don't need any prefix
(specifically: no `s_` or `_` prefix, and generally avoid adding the
file-level common prefix).
## Integer types
MicroPython runs on 16, 32, and 64 bit machines, so it's important to use the
correctly-sized (and signed) integer types. The general guidelines are:
- For most cases use mp_int_t for signed and mp_uint_t for unsigned
integer values. These are guaranteed to be machine-word sized and
therefore big enough to hold the value from a MicroPython small-int
@@ -241,11 +273,13 @@ general guidelines are:
- You can use int/uint, but remember that they may be 16-bits wide.
- If in doubt, use mp_int_t/mp_uint_t.
Comments:
## Comments
- Be concise and only write comments for things that are not obvious.
- Use `// ` prefix, NOT `/* ... */`. No extra fluff.
Memory allocation:
## Memory allocation
- Use m_new, m_renew, m_del (and friends) to allocate and free heap memory.
These macros are defined in py/misc.h.

View File

@@ -67,6 +67,9 @@ The known limitations are:
* static BSS variables are not supported; workaround: use global BSS variables
* thread-local storage variables are not supported on rv32imc; workaround: use
global BSS variables or allocate some space on the heap to store them
So, if your C code has writable data, make sure the data is defined globally,
without an initialiser, and only written to within functions.
@@ -81,7 +84,14 @@ Linker limitation: the native module is not linked against the symbol table of t
full MicroPython firmware. Rather, it is linked against an explicit table of exported
symbols found in ``mp_fun_table`` (in ``py/nativeglue.h``), that is fixed at firmware
build time. It is thus not possible to simply call some arbitrary HAL/OS/RTOS/system
function, for example.
function, for example, unless that resides at a fixed address. In that case, the path
of a linkerscript containing a series of symbol names and their fixed address can be
passed to ``mpy_ld.py`` via the ``--externs`` command line argument. That way symbols
appearing in the linkerscript will take precedence over what is provided from object
files, but at the moment the object files' implementation will still reside in the
final MPY file. The linkerscript parser is limited in its capabilities, and is
currently used only for parsing the ESP8266 port ROM symbols list (see
``ports/esp8266/boards/eagle.rom.addr.v6.ld``).
New symbols can be added to the end of the table and the firmware rebuilt.
The symbols also need to be added to ``tools/mpy_ld.py``'s ``fun_table`` dict in the
@@ -218,6 +228,26 @@ other module, for example::
print(factorial.factorial(10))
# should display 3628800
Using Picolibc when building modules
------------------------------------
Using `Picolibc <https://github.com/picolibc/picolibc>`_ as your C standard
library is not only supported, but in fact it is the default for the rv32imc
platform. However, there are a couple of things worth mentioning to make sure
you don't run into problems later when building code.
Some pre-built Picolibc versions (for example, those provided by Ubuntu Linux
as the ``picolibc-arm-none-eabi``, ``picolibc-riscv64-unknown-elf``, and
``picolibc-xtensa-lx106-elf`` packages) assume thread-local storage (TLS) is
available at runtime, but unfortunately MicroPython modules do not support that
on some architectures (namely ``rv32imc``). This means that some
functionalities provided by Picolibc will default to use TLS, returning an
error either during compilation or during linking.
For an example on how this may affect you, the ``examples/natmod/btree``
example module contains a workaround to make sure ``errno`` works (look for
``__PICOLIBC_ERRNO_FUNCTION`` in the Makefile and follow the trail from there).
Further examples
----------------

View File

@@ -25,7 +25,8 @@ Python 3.6 beta 1 was released on 12 Sep 2016, and a summary of the new features
+--------------------------------------------------------+--------------------------------------------------+-----------------+
| `PEP 468 <https://www.python.org/dev/peps/pep-0468/>`_ | Preserving the order of *kwargs* in a function | |
+--------------------------------------------------------+--------------------------------------------------+-----------------+
| `PEP 487 <https://www.python.org/dev/peps/pep-0487/>`_ | Simpler customization of class creation | |
| `PEP 487 <https://www.python.org/dev/peps/pep-0487/>`_ | Simpler customization of class creation | Partial |
| | | [#setname]_ |
+--------------------------------------------------------+--------------------------------------------------+-----------------+
| `PEP 520 <https://www.python.org/dev/peps/pep-0520/>`_ | Preserving Class Attribute Definition Order | |
+--------------------------------------------------------+--------------------------------------------------+-----------------+
@@ -198,3 +199,7 @@ Changes to built-in modules:
+--------------------------------------------------------------------------------------------------------------+----------------+
| The *compress()* and *decompress()* functions now accept keyword arguments | |
+--------------------------------------------------------------------------------------------------------------+----------------+
.. rubric:: Notes
.. [#setname] Currently, only :func:`__set_name__` is implemented.

View File

@@ -148,6 +148,7 @@ Required keyword arguments for the constructor:
- ``mdc`` and ``mdio`` - :class:`machine.Pin` objects (or integers) specifying
the MDC and MDIO pins.
- ``phy_type`` - Select the PHY device type. Supported devices are
``PHY_GENERIC``,
``PHY_LAN8710``, ``PHY_LAN8720``, ``PHY_IP101``, ``PHY_RTL8201``,
``PHY_DP83848``, ``PHY_KSZ8041`` and ``PHY_KSZ8081``. These values are all
constants defined in the ``network`` module.
@@ -270,8 +271,10 @@ Use the :mod:`time <time>` module::
Timers
------
The ESP32 port has four hardware timers. Use the :ref:`machine.Timer <machine.Timer>` class
with a timer ID from 0 to 3 (inclusive)::
The ESP32 port has one, two or four hardware timers, depending on the ESP32 device type.
There is 1 timer for ESP32C2, 2 timers for ESP32C4, ESP32C6 and ESP32H4, and
4 timers otherwise. Use the :ref:`machine.Timer <machine.Timer>` class
with a timer ID of 0, 0 and 1, or from 0 to 3 (inclusive)::
from machine import Timer
@@ -281,7 +284,8 @@ with a timer ID from 0 to 3 (inclusive)::
tim1 = Timer(1)
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))
The period is in milliseconds.
The period is in milliseconds. When using UART.IRQ_RXIDLE, timer 0 is needed for
the IRQ_RXIDLE mechanism and must not be used otherwise.
Virtual timers are not currently supported on this port.
@@ -383,7 +387,7 @@ for more details.
Use the :ref:`machine.PWM <machine.PWM>` class::
from machine import Pin, PWM
from machine import Pin, PWM, lightsleep
pwm0 = PWM(Pin(0), freq=5000, duty_u16=32768) # create PWM object from a pin
freq = pwm0.freq() # get current frequency
@@ -393,7 +397,7 @@ Use the :ref:`machine.PWM <machine.PWM>` class::
pwm0.duty(256) # set duty cycle from 0 to 1023 as a ratio duty/1023, (now 25%)
duty_u16 = pwm0.duty_u16() # get current duty cycle, range 0-65535
pwm0.duty_u16(2**16*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%)
pwm0.duty_u16(65536*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%)
duty_ns = pwm0.duty_ns() # get current pulse width in ns
pwm0.duty_ns(250_000) # set pulse width in nanoseconds from 0 to 1_000_000_000/freq, (now 25%)
@@ -402,19 +406,35 @@ Use the :ref:`machine.PWM <machine.PWM>` class::
pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go
print(pwm2) # view PWM settings
pwm2.deinit() # turn off PWM on the pin
pwm0 = PWM(Pin(0), duty_u16=16384) # The output is at a high level 25% of the time.
pwm2 = PWM(Pin(2), duty_u16=16384, invert=1) # The output is at a low level 25% of the time.
pwm4 = PWM(Pin(4), lightsleep=True) # Allow PWM during light sleep mode
lightsleep(10*1000) # pwm0, pwm2 goes off, pwm4 stays on during 10s light sleep
# pwm0, pwm2, pwm4 on after 10s light sleep
ESP chips have different hardware peripherals:
===================================================== ======== ======== ========
Hardware specification ESP32 ESP32-S2 ESP32-C3
----------------------------------------------------- -------- -------- --------
Number of groups (speed modes) 2 1 1
Number of timers per group 4 4 4
Number of channels per group 8 8 6
----------------------------------------------------- -------- -------- --------
Different PWM frequencies (groups * timers) 8 4 4
Total PWM channels (Pins, duties) (groups * channels) 16 8 6
===================================================== ======== ======== ========
======================================================= ======== ========= ==========
Hardware specification ESP32 ESP32-S2, ESP32-C2,
ESP32-S3, ESP32-C3,
ESP32-P4 ESP32-C5,
ESP32-C6,
ESP32-H2
------------------------------------------------------- -------- --------- ----------
Number of groups (speed modes) 2 1 1
Number of timers per group 4 4 4
Number of channels per group 8 8 6
------------------------------------------------------- -------- --------- ----------
Different PWM frequencies = (groups * timers) 8 4 4
Total PWM channels (Pins, duties) = (groups * channels) 16 8 6
======================================================= ======== ========= ==========
In light sleep, the ESP32 PWM can only operate in low speed mode, so only 4 timers and
8 channels are available.
A maximum number of PWM channels (Pins) are available on the ESP32 - 16 channels,
but only 8 different PWM frequencies are available, the remaining 8 channels must
@@ -524,14 +544,63 @@ Legacy methods:
Equivalent to ``ADC.block().init(bits=bits)``.
For compatibility, the ``ADC`` object also provides constants matching the
supported ADC resolutions:
The only chip that can switch resolution to a lower one is the normal esp32.
The C2 & S3 are stuck at 12 bits, while the S2 is at 13 bits.
For compatibility, the ``ADC`` object also provides constants matching the
supported ADC resolutions, per chip:
ESP32:
- ``ADC.WIDTH_9BIT`` = 9
- ``ADC.WIDTH_10BIT`` = 10
- ``ADC.WIDTH_11BIT`` = 11
- ``ADC.WIDTH_12BIT`` = 12
ESP32 C3 & S3:
- ``ADC.WIDTH_12BIT`` = 12
ESP32 S2:
- ``ADC.WIDTH_13BIT`` = 13
.. method:: ADC.deinit()
Provided to deinit the adc driver.
Pulse Counter (pin pulse/edge counting)
---------------------------------------
The ESP32 provides up to 8 pulse counter peripherals depending on the hardware,
with id 0..7. These can be configured to count rising and/or falling edges on
any input pin.
Use the :ref:`esp32.PCNT <esp32.PCNT>` class::
from machine import Pin
from esp32 import PCNT
counter = PCNT(0, pin=Pin(2), rising=PCNT.INCREMENT) # create counter
counter.start() # start counter
count = counter.value() # read count, -32768..32767
counter.value(0) # reset counter
count = counter.value(0) # read and reset
The PCNT hardware supports monitoring multiple pins in a single unit to
implement quadrature decoding or up/down signal counters.
See the :ref:`machine.Counter <machine.Counter>` and
:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of
common pulse counting applications::
from machine import Pin, Counter
counter = Counter(0, Pin(2)) # create a counter as above and start it
count = counter.value() # read the count as an arbitrary precision signed integer
encoder = Encoder(0, Pin(12), Pin(14)) # create an encoder and begin counting
count = encoder.value() # read the count as an arbitrary precision signed integer
Note that the id passed to these ``Counter()`` and ``Encoder()`` objects must be
a PCNT id.
Software SPI bus
----------------
@@ -769,6 +838,9 @@ The RMT is ESP32-specific and allows generation of accurate digital pulses with
# The channel resolution is 100ns (1/(source_freq/clock_div)).
r.write_pulses((1, 20, 2, 40), 0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns
The ESP32-C2 family does not include any RMT peripheral, so this class is
unavailable on those SoCs.
OneWire driver
--------------

View File

@@ -11,16 +11,20 @@ compared with the length of a single period (low plus high time). Maximum
duty cycle is when the pin is high all of the time, and minimum is when it is
low all of the time.
* More comprehensive example with all 16 PWM channels and 8 timers::
* More comprehensive example with all **16 PWM channels and 8 timers**::
from time import sleep
from machine import Pin, PWM
try:
f = 100 # Hz
d = 1024 // 16 # 6.25%
pins = (15, 2, 4, 16, 18, 19, 22, 23, 25, 26, 27, 14 , 12, 13, 32, 33)
F = 10000 # Hz
D = 65536 // 16 # 6.25%
pins = (2, 4, 12, 13, 14, 15, 16, 18, 19, 22, 23, 25, 26, 27, 32, 33)
pwms = []
for i, pin in enumerate(pins):
pwms.append(PWM(Pin(pin), freq=f * (i // 2 + 1), duty= 1023 if i==15 else d * (i + 1)))
f = F * (i // 2 + 1)
d = min(65535, D * (i + 1))
pwms.append(PWM(pin, freq=f, duty_u16=d))
sleep(2 / f)
print(pwms[i])
finally:
for pwm in pwms:
@@ -31,65 +35,100 @@ low all of the time.
Output is::
PWM(Pin(15), freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0)
PWM(Pin(2), freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0)
PWM(Pin(4), freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1)
PWM(Pin(16), freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1)
PWM(Pin(18), freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2)
PWM(Pin(19), freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2)
PWM(Pin(22), freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3)
PWM(Pin(23), freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3)
PWM(Pin(25), freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0)
PWM(Pin(26), freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0)
PWM(Pin(27), freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1)
PWM(Pin(14), freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1)
PWM(Pin(12), freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2)
PWM(Pin(13), freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2)
PWM(Pin(32), freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3)
PWM(Pin(33), freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3)
PWM(Pin(2), freq=10000, duty_u16=4096)
PWM(Pin(4), freq=10000, duty_u16=8192)
PWM(Pin(12), freq=20000, duty_u16=12288)
PWM(Pin(13), freq=20000, duty_u16=16384)
PWM(Pin(14), freq=30030, duty_u16=20480)
PWM(Pin(15), freq=30030, duty_u16=24576)
PWM(Pin(16), freq=40000, duty_u16=28672)
PWM(Pin(18), freq=40000, duty_u16=32768)
PWM(Pin(19), freq=50000, duty_u16=36864)
PWM(Pin(22), freq=50000, duty_u16=40960)
PWM(Pin(23), freq=60060, duty_u16=45056)
PWM(Pin(25), freq=60060, duty_u16=49152)
PWM(Pin(26), freq=69930, duty_u16=53248)
PWM(Pin(27), freq=69930, duty_u16=57344)
PWM(Pin(32), freq=80000, duty_u16=61440)
PWM(Pin(33), freq=80000, duty_u16=65535)
* Example of a smooth frequency change::
* Example of a **smooth frequency change**::
from time import sleep
from machine import Pin, PWM
F_MIN = 500
F_MAX = 1000
F_MIN = 1000
F_MAX = 10000
f = F_MIN
delta_f = 1
delta_f = F_MAX // 50
p = PWM(Pin(5), f)
print(p)
pwm = PWM(Pin(27), f)
while True:
p.freq(f)
sleep(10 / F_MIN)
pwm.freq(f)
sleep(1 / f)
sleep(0.1)
print(pwm)
f += delta_f
if f >= F_MAX or f <= F_MIN:
if f > F_MAX or f < F_MIN:
delta_f = -delta_f
print()
if f > F_MAX:
f = F_MAX
elif f < F_MIN:
f = F_MIN
See PWM wave at Pin(5) with an oscilloscope.
See PWM wave on Pin(27) with an oscilloscope.
* Example of a smooth duty change::
Output is::
PWM(Pin(27), freq=998, duty_u16=32768)
PWM(Pin(27), freq=1202, duty_u16=32768)
PWM(Pin(27), freq=1401, duty_u16=32768)
PWM(Pin(27), freq=1598, duty_u16=32768)
...
PWM(Pin(27), freq=9398, duty_u16=32768)
PWM(Pin(27), freq=9615, duty_u16=32768)
PWM(Pin(27), freq=9804, duty_u16=32768)
PWM(Pin(27), freq=10000, duty_u16=32768)
PWM(Pin(27), freq=10000, duty_u16=32768)
PWM(Pin(27), freq=9804, duty_u16=32768)
PWM(Pin(27), freq=9615, duty_u16=32768)
PWM(Pin(27), freq=9398, duty_u16=32768)
...
PWM(Pin(27), freq=1598, duty_u16=32768)
PWM(Pin(27), freq=1401, duty_u16=32768)
PWM(Pin(27), freq=1202, duty_u16=32768)
PWM(Pin(27), freq=998, duty_u16=32768)
* Example of a **smooth duty change**::
from time import sleep
from machine import Pin, PWM
DUTY_MAX = 2**16 - 1
DUTY_MAX = 65535
duty_u16 = 0
delta_d = 16
delta_d = 256
p = PWM(Pin(5), 1000, duty_u16=duty_u16)
print(p)
pwm = PWM(Pin(27), freq=1000, duty_u16=duty_u16)
while True:
p.duty_u16(duty_u16)
pwm.duty_u16(duty_u16)
sleep(2 / pwm.freq())
print(pwm)
sleep(1 / 1000)
if duty_u16 >= DUTY_MAX:
print()
sleep(2)
elif duty_u16 <= 0:
print()
sleep(2)
duty_u16 += delta_d
if duty_u16 >= DUTY_MAX:
@@ -99,9 +138,106 @@ low all of the time.
duty_u16 = 0
delta_d = -delta_d
See PWM wave at Pin(5) with an oscilloscope.
PWM wave on Pin(27) with an oscilloscope.
Note: the Pin.OUT mode does not need to be specified. The channel is initialized
Output is::
PWM(Pin(27), freq=998, duty_u16=0)
PWM(Pin(27), freq=998, duty_u16=256)
PWM(Pin(27), freq=998, duty_u16=512)
PWM(Pin(27), freq=998, duty_u16=768)
PWM(Pin(27), freq=998, duty_u16=1024)
...
PWM(Pin(27), freq=998, duty_u16=64512)
PWM(Pin(27), freq=998, duty_u16=64768)
PWM(Pin(27), freq=998, duty_u16=65024)
PWM(Pin(27), freq=998, duty_u16=65280)
PWM(Pin(27), freq=998, duty_u16=65535)
PWM(Pin(27), freq=998, duty_u16=65279)
PWM(Pin(27), freq=998, duty_u16=65023)
PWM(Pin(27), freq=998, duty_u16=64767)
PWM(Pin(27), freq=998, duty_u16=64511)
...
PWM(Pin(27), freq=998, duty_u16=1023)
PWM(Pin(27), freq=998, duty_u16=767)
PWM(Pin(27), freq=998, duty_u16=511)
PWM(Pin(27), freq=998, duty_u16=255)
PWM(Pin(27), freq=998, duty_u16=0)
* Example of a **smooth duty change and PWM output inversion**::
from utime import sleep
from machine import Pin, PWM
try:
DUTY_MAX = 65535
duty_u16 = 0
delta_d = 65536 // 32
pwm = PWM(Pin(27))
pwmi = PWM(Pin(32), invert=1)
while True:
pwm.duty_u16(duty_u16)
pwmi.duty_u16(duty_u16)
duty_u16 += delta_d
if duty_u16 >= DUTY_MAX:
duty_u16 = DUTY_MAX
delta_d = -delta_d
elif duty_u16 <= 0:
duty_u16 = 0
delta_d = -delta_d
sleep(.01)
print(pwm)
print(pwmi)
finally:
try:
pwm.deinit()
except:
pass
try:
pwmi.deinit()
except:
pass
Output is::
PWM(Pin(27), freq=5000, duty_u16=0)
PWM(Pin(32), freq=5000, duty_u16=32768, invert=1)
PWM(Pin(27), freq=5000, duty_u16=2048)
PWM(Pin(32), freq=5000, duty_u16=2048, invert=1)
PWM(Pin(27), freq=5000, duty_u16=4096)
PWM(Pin(32), freq=5000, duty_u16=4096, invert=1)
PWM(Pin(27), freq=5000, duty_u16=6144)
PWM(Pin(32), freq=5000, duty_u16=6144, invert=1)
PWM(Pin(27), freq=5000, duty_u16=8192)
PWM(Pin(32), freq=5000, duty_u16=8192, invert=1)
...
See PWM waves on Pin(27) and Pin(32) with an oscilloscope.
Note: New PWM parameters take effect in the next PWM cycle.
pwm = PWM(2, duty=512)
print(pwm)
>>> PWM(Pin(2), freq=5000, duty=1023) # the duty is not relevant
pwm.init(freq=2, duty=64)
print(pwm)
>>> PWM(Pin(2), freq=2, duty=16) # the duty is not relevant
time.sleep(1 / 2) # wait one PWM period
print(pwm)
>>> PWM(Pin(2), freq=2, duty=64) # the duty is actual
Note: machine.freq(20_000_000) reduces the highest PWM frequency to 10 MHz.
Note: the Pin.OUT mode does not need to be specified. The channel is initialized
to PWM mode internally once for each Pin that is passed to the PWM constructor.
The following code is wrong::

View File

@@ -764,4 +764,5 @@ Constructor
The **value** can be either:
- A 16-bit integer. e.g. ``0x2908``.
- An object with the buffer protocol and that is 2, 4 or 16 bytes long, e.g. ``b'\x08\x29'``.
- A 128-bit UUID string. e.g. ``'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'``.

View File

@@ -151,10 +151,10 @@ Constants
.. data:: INCL
A flag for `keys()`, `values()`, `items()` methods to specify that
A flag for :meth:`btree.keys`, :meth:`btree.values`, :meth:`btree.items` methods to specify that
scanning should be inclusive of the end key.
.. data:: DESC
A flag for `keys()`, `values()`, `items()` methods to specify that
A flag for :meth:`btree.keys`, :meth:`btree.values`, :meth:`btree.items` methods to specify that
scanning should be in descending direction of keys.

View File

@@ -18,23 +18,31 @@ Functions
Configure whether or not a touch will wake the device from sleep.
*wake* should be a boolean value.
.. note:: This is only available for boards that have touch sensor support.
.. function:: wake_on_ulp(wake)
Configure whether or not the Ultra-Low-Power co-processor can wake the
device from sleep. *wake* should be a boolean value.
.. note:: This is only available for boards that have ULP coprocessor support.
.. function:: wake_on_ext0(pin, level)
Configure how EXT0 wakes the device from sleep. *pin* can be ``None``
or a valid Pin object. *level* should be ``esp32.WAKEUP_ALL_LOW`` or
``esp32.WAKEUP_ANY_HIGH``.
.. note:: This is only available for boards that have ext0 support.
.. function:: wake_on_ext1(pins, level)
Configure how EXT1 wakes the device from sleep. *pins* can be ``None``
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW``
or ``esp32.WAKEUP_ANY_HIGH``.
.. note:: This is only available for boards that have ext1 support.
.. function:: gpio_deep_sleep_hold(enable)
Configure whether non-RTC GPIO pin configuration is retained during
@@ -80,6 +88,29 @@ Functions
The result of :func:`gc.mem_free()` is the total of the current "free"
and "max new split" values printed by :func:`micropython.mem_info()`.
.. function:: idf_task_info()
Returns information about running ESP-IDF/FreeRTOS tasks, which include
MicroPython threads. This data is useful to gain insight into how much time
tasks spend running or if they are blocked for significant parts of time,
and to determine if allocated stacks are fully utilized or might be reduced.
``CONFIG_FREERTOS_USE_TRACE_FACILITY=y`` must be set in the board
configuration to make this method available. Additionally configuring
``CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y`` and
``CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y`` is recommended to be able to
retrieve the total and per-task runtime and the core ID respectively.
The return value is a 2-tuple where the first value is the total runtime,
and the second a list of tasks. Each task is a 7-tuple containing: the task
ID, name, current state, priority, runtime, stack high water mark, and the
ID of the core it is running on. Runtime and core ID will be None when the
respective FreeRTOS configuration option is not enabled.
.. note:: For an easier to use output based on this function you can use the
`utop library <https://github.com/micropython/micropython-lib/tree/master/micropython/utop>`_,
which implements a live overview similar to the Unix ``top`` command.
Flash partitions
----------------
@@ -164,6 +195,151 @@ Constants
Used in `idf_heap_info`.
.. _esp32.PCNT:
PCNT
----
This class provides access to the ESP32 hardware support for pulse counting.
There are 8 pulse counter units, with id 0..7.
See the :ref:`machine.Counter <machine.Counter>` and
:ref:`machine.Encoder <machine.Encoder>` classes for simpler and portable
abstractions of common pulse counting applications. These classes are
implemented as thin Python shims around :class:`PCNT`.
.. class:: PCNT(id, *, ...)
Returns the singleton PCNT instance for the given unit ``id``.
Keyword arguments are passed to the ``init()`` method as described
below.
.. method:: PCNT.init(*, ...)
(Re-)initialise a pulse counter unit. Supported keyword arguments are:
- ``channel``: see description below
- ``pin``: the input Pin to monitor for pulses
- ``rising``: an action to take on a rising edge - one of
``PCNT.INCREMENT``, ``PCNT.DECREMENT`` or ``PCNT.IGNORE`` (the default)
- ``falling``: an action to take on a falling edge (takes the save values
as the ``rising`` argument).
- ``mode_pin``: ESP32 pulse counters support monitoring a second pin and
altering the behaviour of the counter based on its level - set this
keyword to any input Pin
- ``mode_low``: set to either ``PCNT.HOLD`` or ``PCNT.REVERSE`` to
either suspend counting or reverse the direction of the counter (i.e.,
``PCNT.INCREMENT`` behaves as ``PCNT.DECREMENT`` and vice versa)
when ``mode_pin`` is low
- ``mode_high``: as ``mode_low`` but for the behaviour when ``mode_pin``
is high
- ``filter``: set to a value 1..1023, in ticks of the 80MHz clock, to
enable the pulse width filter
- ``min``: set to the minimum level of the counter value when
decrementing (-32768..-1) or 0 to disable
- ``max``: set to the maximum level of the counter value when
incrementing (1..32767) or 0 to disable
- ``threshold0``: sets the counter value for the
``PCNT.IRQ_THRESHOLD0`` event (see ``irq`` method)
- ``threshold1``: sets the counter value for the
``PCNT.IRQ_THRESHOLD1`` event (see ``irq`` method)
- ``value``: can be set to ``0`` to reset the counter value
The hardware initialisation is done in stages and so some of the keyword
arguments can be used in groups or in isolation to partially reconfigure a
unit:
- the ``pin`` keyword (optionally combined with ``mode_pin``) can be used
to change just the bound pin(s)
- ``rising``, ``falling``, ``mode_low`` and ``mode_high`` can be used
(singly or together) to change the counting logic - omitted keywords
use their default (``PCNT.IGNORE`` or ``PCNT.NORMAL``)
- ``filter`` can be used to change only the pulse width filter (with 0
disabling it)
- each of ``min``, ``max``, ``threshold0`` and ``threshold1`` can
be used to change these limit/event values individually; however,
setting any will reset the counter to zero (i.e., they imply
``value=0``)
Each pulse counter unit supports two channels, 0 and 1, each able to
monitor different pins with different counting logic but updating the same
counter value. Use ``channel=1`` with the ``pin``, ``rising``, ``falling``,
``mode_pin``, ``mode_low`` and ``mode_high`` keywords to configure the
second channel.
The second channel can be used to configure 4X quadrature decoding with a
single counter unit::
pin_a = Pin(2, Pin.INPUT, pull=Pin.PULL_UP)
pin_b = Pin(3, Pin.INPUT, pull=Pin.PULL_UP)
rotary = PCNT(0, min=-32000, max=32000)
rotary.init(channel=0, pin=pin_a, falling=PCNT.INCREMENT, rising=PCNT.DECREMENT, mode_pin=pin_b, mode_low=PCNT.REVERSE)
rotary.init(channel=1, pin=pin_b, falling=PCNT.DECREMENT, rising=PCNT.INCREMENT, mode_pin=pin_a, mode_low=PCNT.REVERSE)
rotary.start()
.. method:: PCNT.value([value])
Call this method with no arguments to return the current counter value.
If the optional *value* argument is set to ``0`` then the counter is
reset (but the previous value is returned). Read and reset is not atomic and
so it is possible for a pulse to be missed. Any value other than ``0`` will
raise an error.
.. method:: PCNT.irq(handler=None, trigger=PCNT.IRQ_ZERO)
ESP32 pulse counters support interrupts on these counter events:
- ``PCNT.IRQ_ZERO``: the counter has reset to zero
- ``PCNT.IRQ_MIN``: the counter has hit the ``min`` value
- ``PCNT.IRQ_MAX``: the counter has hit the ``max`` value
- ``PCNT.IRQ_THRESHOLD0``: the counter has hit the ``threshold0`` value
- ``PCNT.IRQ_THRESHOLD1``: the counter has hit the ``threshold1`` value
``trigger`` should be a bit-mask of the desired events OR'ed together. The
``handler`` function should take a single argument which is the
:class:`PCNT` instance that raised the event.
This method returns a callback object. The callback object can be used to
access the bit-mask of events that are outstanding on the PCNT unit.::
def pcnt_irq(pcnt):
flags = pcnt.irq().flags()
if flags & PCNT.IRQ_ZERO:
# reset
if flags & PCNT.IRQ_MAX:
# overflow...
... etc
pcnt.irq(handler=pcnt_irq, trigger=PCNT.IRQ_ZERO | PCNT.IRQ_MAX | ...)
**Note:** Accessing ``irq.flags()`` will clear the flags, so only call it
once per invocation of the handler.
The handler is called with the MicroPython scheduler and so will run at a
point after the interrupt. If another interrupt occurs before the handler
has been called then the events will be coalesced together into a single
call and the bit mask will indicate all events that have occurred.
To avoid race conditions between a handler being called and retrieving the
current counter value, the ``value()`` method will force execution of any
pending events before returning the current counter value (and potentially
resetting the value).
Only one handler can be in place per-unit. Set ``handler`` to ``None`` to
disable the event interrupt.
.. Note::
ESP32 pulse counters reset to *zero* when reaching the minimum or maximum
value. Thus the ``IRQ_ZERO`` event will also trigger when either of these
events occurs.
See the :ref:`machine.Counter <machine.Counter>` and
:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of
common pulse counting applications.
.. _esp32.RMT:
RMT

View File

@@ -137,6 +137,18 @@ Other methods
is compared to the value from *palette*, not to the value directly from
*fbuf*.)
*fbuf* can be another FrameBuffer instance, or a tuple or list of the form::
(buffer, width, height, format)
or::
(buffer, width, height, format, stride)
This matches the signature of the FrameBuffer constructor, and the elements
of the tuple/list are the same as the arguments to the constructor except that
the *buffer* here can be read-only.
The *palette* argument enables blitting between FrameBuffers with differing
formats. Typical usage is to render a monochrome or grayscale glyph/icon to
a color display. The *palette* is a FrameBuffer instance whose format is

View File

@@ -0,0 +1,93 @@
.. currentmodule:: machine
.. _machine.Counter:
class Counter -- pulse counter
==============================
Counter implements pulse counting by monitoring an input signal and counting
rising or falling edges.
Minimal example usage::
from machine import Pin, Counter
counter = Counter(0, Pin(0, Pin.IN)) # create Counter for pin 0 and begin counting
value = counter.value() # retrieve current pulse count
Availability: **ESP32**
Constructors
------------
.. class:: Counter(id, ...)
Returns the singleton Counter object for the the given *id*. Values of *id*
depend on a particular port and its hardware. Values 0, 1, etc. are commonly
used to select hardware block #0, #1, etc.
Additional arguments are passed to the :meth:`init` method described below,
and will cause the Counter instance to be re-initialised and reset.
On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`.
Methods
-------
.. method:: Counter.init(src, *, ...)
Initialise and reset the Counter with the given parameters:
- *src* specifies the input pin as a :ref:`machine.Pin <machine.Pin>` object.
May be omitted on ports that have a predefined pin for a given hardware
block.
Additional keyword-only parameters that may be supported by a port are:
- *edge* specifies the edge to count. Either ``Counter.RISING`` (the default)
or ``Counter.FALLING``. *(Supported on ESP32)*
- *direction* specifies the direction to count. Either ``Counter.UP`` (the
default) or ``Counter.DOWN``. *(Supported on ESP32)*
- *filter_ns* specifies a minimum period of time in nanoseconds that the
source signal needs to be stable for a pulse to be counted. Implementations
should use the longest filter supported by the hardware that is less than
or equal to this value. The default is 0 (no filter). *(Supported on ESP32)*
.. method:: Counter.deinit()
Stops the Counter, disabling any interrupts and releasing hardware resources.
A Soft Reset should deinitialize all Counter objects.
.. method:: Counter.value([value])
Get, and optionally set, the counter value as a signed integer.
Implementations must aim to do the get and set atomically (i.e. without
leading to skipped counts).
This counter value could exceed the range of a :term:`small integer`, which
means that calling :meth:`Counter.value` could cause a heap allocation, but
implementations should aim to ensure that internal state only uses small
integers and therefore will not allocate until the user calls
:meth:`Counter.value`.
For example, on ESP32, the internal state counts overflows of the hardware
counter (every 32000 counts), which means that it will not exceed the small
integer range until ``2**30 * 32000`` counts (slightly over 1 year at 1MHz).
In general, it is recommended that you should use ``Counter.value(0)`` to reset
the counter (i.e. to measure the counts since the last call), and this will
avoid this problem.
Constants
---------
.. data:: Counter.RISING
Counter.FALLING
Select the pulse edge.
.. data:: Counter.UP
Counter.DOWN
Select the counting direction.

View File

@@ -0,0 +1,72 @@
.. currentmodule:: machine
.. _machine.Encoder:
class Encoder -- quadrature decoding
====================================
Encoder implements decoding of quadrature signals as commonly output from
rotary encoders, by counting either up or down depending on the order of two
input pulses.
Minimal example usage::
from machine import Pin, Encoder
counter = Counter(0, Pin(0, Pin.IN), Pin(1, Pin.IN)) # create Encoder for pins 0, 1 and begin counting
value = counter.value() # retrieve current count
Availability: **ESP32**
Constructors
------------
.. class:: Encoder(id, ...)
Returns the singleton Encoder object for the the given *id*. Values of *id*
depend on a particular port and its hardware. Values 0, 1, etc. are commonly
used to select hardware block #0, #1, etc.
Additional arguments are passed to the :meth:`init` method described below,
and will cause the Encoder instance to be re-initialised and reset.
On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`.
Methods
-------
.. method:: Encoder.init(phase_a, phase_b, *, ...)
Initialise and reset the Encoder with the given parameters:
- *phase_a* specifies the first input pin as a
:ref:`machine.Pin <machine.Pin>` object.
- *phase_b* specifies the second input pin as a
:ref:`machine.Pin <machine.Pin>` object.
These pins may be omitted on ports that have predefined pins for a given
hardware block.
Additional keyword-only parameters that may be supported by a port are:
- *filter_ns* specifies a minimum period of time in nanoseconds that the
source signal needs to be stable for a pulse to be counted. Implementations
should use the longest filter supported by the hardware that is less than
or equal to this value. The default is 0 (no filter). *(Supported on ESP32)*
- *phases* specifies the number of signal edges to count and thus the
granularity of the decoding. e.g. 4 phases corresponds to "4x quadrature
decoding", and will result in four counts per pulse. Ports may support
either 1, 2, or 4 phases and the default is 1 phase. *(Supported on ESP32)*
.. method:: Encoder.deinit()
Stops the Encoder, disabling any interrupts and releasing hardware resources.
A Soft Reset should deinitialize all Encoder objects.
.. method:: Encoder.value([value])
Get, and optionally set, the encoder value as a signed integer.
Implementations should aim to do the get and set atomically.
See :meth:`machine.Counter.value` for details about overflow of this value.

View File

@@ -0,0 +1,174 @@
.. currentmodule:: machine
.. _machine.I2CTarget:
class I2CTarget -- an I2C target device
=======================================
An I2C target is a device which connects to an I2C bus and is controlled by an
I2C controller. I2C targets can take many forms. The :class:`machine.I2CTarget`
class implements an I2C target that can be configured as a memory/register device,
or as an arbitrary I2C device by using callbacks (if supported by the port).
Example usage for the case of a memory device::
from machine import I2CTarget
# Create the backing memory for the I2C target.
mem = bytearray(8)
# Create an I2C target. Depending on the port, extra parameters
# may be required to select the peripheral and/or pins to use.
i2c = I2CTarget(addr=67, mem=mem)
# At this point an I2C controller can read and write `mem`.
...
# Deinitialise the I2C target.
i2c.deinit()
Note that some ports require an ``id``, and maybe ``scl`` and ``sda`` pins, to be
passed to the `I2CTarget` constructor, to select the hardware I2C instance and
pins that it connects to.
When configured as a memory device, it's also possible to register to receive events.
For example to be notified when the memory is read/written::
from machine import I2CTarget
# Define an IRQ handler, for I2C events.
def irq_handler(i2c_target):
flags = i2c_target.irq().flags()
if flags & I2CTarget.IRQ_END_READ:
print("controller read target at addr", i2c_target.memaddr)
if flags & I2CTarget.IRQ_END_WRITE:
print("controller wrote target at addr", i2c_target.memaddr)
# Create the I2C target and register to receive default events.
mem = bytearray(8)
i2c = I2CTarget(addr=67, mem=mem)
i2c.irq(irq_handler)
More complicated I2C devices can be implemented using the full set of events. For
example, to see the raw events as they are triggered::
from machine import I2CTarget
# Define an IRQ handler that prints the event id and responds to reads/writes.
def irq_handler(i2c_target, buf=bytearray(1)):
flags = i2c_target.irq().flags()
print(flags)
if flags & I2CTarget.IRQ_READ_REQ:
i2c_target.write(buf)
if flags & I2CTarget.IRQ_WRITE_REQ:
i2c_target.readinto(buf)
# Create the I2C target and register to receive all events.
i2c = I2CTarget(addr=67)
all_triggers = (
I2CTarget.IRQ_ADDR_MATCH_READ
| I2CTarget.IRQ_ADDR_MATCH_WRITE
| I2CTarget.IRQ_READ_REQ
| I2CTarget.IRQ_WRITE_REQ
| I2CTarget.IRQ_END_READ
| I2CTarget.IRQ_END_WRITE
)
i2c.irq(irq_handler, trigger=all_triggers, hard=True)
Constructors
------------
.. class:: I2CTarget(id, addr, *, addrsize=7, mem=None, mem_addrsize=8, scl=None, sda=None)
Construct and return a new I2CTarget object using the following parameters:
- *id* identifies a particular I2C peripheral. Allowed values depend on the
particular port/board. Some ports have a default in which case this parameter
can be omitted.
- *addr* is the I2C address of the target.
- *addrsize* is the number of bits in the I2C target address. Valid values
are 7 and 10.
- *mem* is an object with the buffer protocol that is writable. If not
specified then there is no backing memory and data must be read/written
using the :meth:`I2CTarget.readinto` and :meth:`I2CTarget.write` methods.
- *mem_addrsize* is the number of bits in the memory address. Valid values
are 0, 8, 16, 24 and 32.
- *scl* is a pin object specifying the pin to use for SCL.
- *sda* is a pin object specifying the pin to use for SDA.
Note that some ports/boards will have default values of *scl* and *sda*
that can be changed in this constructor. Others will have fixed values
of *scl* and *sda* that cannot be changed.
General Methods
---------------
.. method:: I2CTarget.deinit()
Deinitialise the I2C target. After this method is called the hardware will no
longer respond to requests on the I2C bus, and no other methods can be called.
.. method:: I2CTarget.readinto(buf)
Read into the given buffer any pending bytes written by the I2C controller.
Returns the number of bytes read.
.. method:: I2CTarget.write(buf)
Write out the bytes from the given buffer, to be passed to the I2C controller
after it sends a read request. Returns the number of bytes written. Most ports
only accept one byte at a time to this method.
.. method:: I2CTarget.irq(handler=None, trigger=IRQ_END_READ|IRQ_END_WRITE, hard=False)
Configure an IRQ *handler* to be called when an event occurs. The possible events are
given by the following constants, which can be or'd together and passed to the *trigger*
argument:
- ``IRQ_ADDR_MATCH_READ`` indicates that the target was addressed by a
controller for a read transaction.
- ``IRQ_ADDR_MATCH_READ`` indicates that the target was addressed by a
controller for a write transaction.
- ``IRQ_READ_REQ`` indicates that the controller is requesting data, and this
request must be satisfied by calling `I2CTarget.write` with the data to be
passed back to the controller.
- ``IRQ_WRITE_REQ`` indicates that the controller has written data, and the
data must be read by calling `I2CTarget.readinto`.
- ``IRQ_END_READ`` indicates that the controller has finished a read transaction.
- ``IRQ_END_WRITE`` indicates that the controller has finished a write transaction.
Not all triggers are available on all ports. If a port has the constant then that
event is available.
Note the following restrictions:
- ``IRQ_ADDR_MATCH_READ``, ``IRQ_ADDR_MATCH_READ``, ``IRQ_READ_REQ`` and
``IRQ_WRITE_REQ`` must be handled by a hard IRQ callback (with the *hard* argument
set to ``True``). This is because these events have very strict timing requirements
and must usually be satisfied synchronously with the hardware event.
- ``IRQ_END_READ`` and ``IRQ_END_WRITE`` may be handled by either a soft or hard
IRQ callback (although note that all events must be registered with the same handler,
so if any events need a hard callback then all events must be hard).
- If a memory buffer has been supplied in the constructor then ``IRQ_END_WRITE``
is not emitted for the transaction that writes the memory address. This is to
allow ``IRQ_END_READ`` and ``IRQ_END_WRITE`` to function correctly as soft IRQ
callbacks, where the IRQ handler may be called quite some time after the actual
hardware event.
.. attribute:: I2CTarget.memaddr
The integer value of the most recent memory address that was selected by the I2C
controller (only valid if ``mem`` was specified in the constructor).
Constants
---------
.. data:: I2CTarget.IRQ_ADDR_MATCH_READ
I2CTarget.IRQ_ADDR_MATCH_WRITE
I2CTarget.IRQ_READ_REQ
I2CTarget.IRQ_WRITE_REQ
I2CTarget.IRQ_END_READ
I2CTarget.IRQ_END_WRITE
IRQ trigger sources.

View File

@@ -11,20 +11,20 @@ Example usage::
from machine import PWM
pwm = PWM(pin, freq=50, duty_u16=8192) # create a PWM object on a pin
# and set freq and duty
pwm.duty_u16(32768) # set duty to 50%
# and set freq 50 Hz and duty 12.5%
pwm.duty_u16(32768) # set duty to 50%
# reinitialise with a period of 200us, duty of 5us
pwm.init(freq=5000, duty_ns=5000)
pwm.duty_ns(3000) # set pulse width to 3us
pwm.duty_ns(3000) # set pulse width to 3us
pwm.deinit()
Constructors
------------
.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert)
.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert=False)
Construct and return a new PWM object using the following parameters:
@@ -40,7 +40,7 @@ Constructors
Setting *freq* may affect other PWM objects if the objects share the same
underlying PWM generator (this is hardware specific).
Only one of *duty_u16* and *duty_ns* should be specified at a time.
*invert* is not available at all ports.
*invert* is available only on the esp32, mimxrt, nrf, rp2, samd and zephyr ports.
Methods
-------
@@ -116,10 +116,10 @@ Limitations of PWM
resolution of 8 bit, not 16-bit as may be expected. In this case, the lowest
8 bits of *duty_u16* are insignificant. So::
pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2)
pwm=PWM(Pin(13), freq=300_000, duty_u16=65536//2)
and::
pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2 + 255)
pwm=PWM(Pin(13), freq=300_000, duty_u16=65536//2 + 255)
will generate PWM with the same 50% duty cycle.

View File

@@ -224,7 +224,8 @@ Methods
.. note::
- The ESP32 port does not support the option hard=True.
- The ESP32 port does not support the option hard=True. It uses Timer(0)
for UART.IRQ_RXIDLE, so this timer cannot be used for other means.
- The rp2 port's UART.IRQ_TXIDLE is only triggered when the message
is longer than 5 characters and the trigger happens when still 5 characters

View File

@@ -264,9 +264,12 @@ Classes
machine.UART.rst
machine.SPI.rst
machine.I2C.rst
machine.I2CTarget.rst
machine.I2S.rst
machine.RTC.rst
machine.Timer.rst
machine.Counter.rst
machine.Encoder.rst
machine.WDT.rst
machine.SD.rst
machine.SDCard.rst

View File

@@ -58,6 +58,11 @@ Methods
- *pull_thresh* is the threshold in bits before auto-pull or conditional
re-pulling is triggered.
Note: pins used for *in_base* need to be configured manually for input (or
otherwise) so that the PIO can see the desired signal (they could be input
pins, output pins, or connected to a different peripheral). The *jmp_pin*
can also be configured manually, but by default will be an input pin.
.. method:: StateMachine.active([value])
Gets or sets whether the state machine is currently running.

View File

@@ -227,22 +227,28 @@ Methods
has the same "no short writes" policy for blocking sockets, and will return
number of bytes sent on non-blocking sockets.
.. method:: socket.recv(bufsize)
.. method:: socket.recv(bufsize, [flags])
Receive data from the socket. The return value is a bytes object representing the data
received. The maximum amount of data to be received at once is specified by bufsize.
Most ports support the optional *flags* argument. Available *flags* are defined as constants
in the socket module and have the same meaning as in CPython. ``MSG_PEEK`` and ``MSG_DONTWAIT``
are supported on all ports which accept the *flags* argument.
.. method:: socket.sendto(bytes, address)
Send data to the socket. The socket should not be connected to a remote socket, since the
destination socket is specified by *address*.
.. method:: socket.recvfrom(bufsize)
.. method:: socket.recvfrom(bufsize, [flags])
Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a
bytes object representing the data received and *address* is the address of the socket sending
the data.
See the `recv` function for an explanation of the optional *flags* argument.
.. method:: socket.setsockopt(level, optname, value)
Set the value of the given socket option. The needed symbolic constants are defined in the

View File

@@ -66,7 +66,7 @@ class SSLContext
Set the available ciphers for sockets created with this context. *ciphers* should be
a list of strings in the `IANA cipher suite format <https://wiki.mozilla.org/Security/Cipher_Suites>`_ .
.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None)
.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None, client_id=None)
Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, wrapping the underlying stream.
@@ -89,6 +89,9 @@ class SSLContext
server certificate. It also sets the name for Server Name Indication (SNI), allowing the server
to present the proper certificate.
- *client_id* is a MicroPython-specific extension argument used only when implementing a DTLS
Server. See :ref:`dtls` for details.
.. warning::
Some implementations of ``ssl`` module do NOT validate server certificates,
@@ -117,6 +120,8 @@ Exceptions
This exception does NOT exist. Instead its base class, OSError, is used.
.. _dtls:
DTLS support
------------
@@ -125,16 +130,47 @@ DTLS support
This is a MicroPython extension.
This module supports DTLS in client and server mode via the `PROTOCOL_DTLS_CLIENT`
and `PROTOCOL_DTLS_SERVER` constants that can be used as the ``protocol`` argument
of `SSLContext`.
On most ports, this module supports DTLS in client and server mode via the
`PROTOCOL_DTLS_CLIENT` and `PROTOCOL_DTLS_SERVER` constants that can be used as
the ``protocol`` argument of `SSLContext`.
In this case the underlying socket is expected to behave as a datagram socket (i.e.
like the socket opened with ``socket.socket`` with ``socket.AF_INET`` as ``af`` and
``socket.SOCK_DGRAM`` as ``type``).
DTLS is only supported on ports that use mbed TLS, and it is not enabled by default:
it requires enabling ``MBEDTLS_SSL_PROTO_DTLS`` in the specific port configuration.
DTLS is only supported on ports that use mbedTLS, and it is enabled by default
in most configurations but can be manually disabled by defining
``MICROPY_PY_SSL_DTLS`` to 0.
DTLS server support
^^^^^^^^^^^^^^^^^^^
MicroPython's DTLS server support is configured with "Hello Verify" as required
for DTLS 1.2. This is transparent for DTLS clients, but there are relevant
considerations when implementing a DTLS server in MicroPython:
- The server should pass an additional argument *client_id* when calling
`SSLContext.wrap_socket()`. This ID must be a `bytes` object (or similar) with
a transport-specific identifier representing the client.
The simplest approach is to convert the tuple of ``(client_ip, client_port)``
returned from ``socket.recv_from()`` into a byte string, i.e.::
_, client_addr = sock.recvfrom(1, socket.MSG_PEEK)
sock.connect(client_addr) # Connect back to the client
sock = ssl_ctx.wrap_socket(sock, server_side=True,
client_id=repr(client_addr).encode())
- The first time a client connects, the server call to ``wrap_socket`` will fail
with a `OSError` error "Hello Verify Required". This is because the DTLS
"Hello Verify" cookie is not yet known by the client. If the same client
connects a second time then ``wrap_socket`` will succeed.
- DTLS cookies for "Hello Verify" are associated with the `SSLContext` object,
so the same `SSLContext` object should be used to wrap a subsequent connection
from the same client. The cookie implementation includes a timeout and has
constant memory use regardless of how many clients connect, so it's OK to
reuse the same `SSLContext` object for the lifetime of the server.
Constants
---------

View File

@@ -77,6 +77,8 @@ Constants
* *_mpy* - supported mpy file-format version (optional attribute)
* *_build* - string that can help identify the configuration that
MicroPython was built with
* *_thread* - optional string attribute, exists if the target has threading
and is either "GIL" or "unsafe"
This object is the recommended way to distinguish MicroPython from other
Python implementations (note that it still may not exist in the very
@@ -95,6 +97,14 @@ Constants
* On microcontroller targets, the first element is the board name and the second
element (if present) is the board variant, for example ``'RPI_PICO2-RISCV'``
The *_thread* entry was added in version 1.26.0 and if it exists then the
target has the ``_thread`` module. If the target enables the GIL (global
interpreter lock) then this attribute is ``"GIL"``. Otherwise the attribute
is ``"unsafe"`` and the target has threading but does not enable the GIL,
and mutable Python objects (such as `bytearray`, `list` and `dict`) that are
shared amongst threads must be protected explicitly by locks such as
``_thread.allocate_lock``.
.. admonition:: Difference to CPython
:class: attention

View File

@@ -9,9 +9,10 @@
The ``time`` module provides functions for getting the current time and date,
measuring time intervals, and for delays.
**Time Epoch**: Unix port uses standard for POSIX systems epoch of
1970-01-01 00:00:00 UTC. However, some embedded ports use epoch of
2000-01-01 00:00:00 UTC. Epoch year may be determined with ``gmtime(0)[0]``.
**Time Epoch**: The unix, windows, webassembly, alif, mimxrt and rp2 ports
use the standard for POSIX systems epoch of 1970-01-01 00:00:00 UTC.
The other embedded ports use an epoch of 2000-01-01 00:00:00 UTC.
Epoch year may be determined with ``gmtime(0)[0]``.
**Maintaining actual calendar date/time**: This requires a
Real Time Clock (RTC). On systems with underlying OS (including some
@@ -57,11 +58,11 @@ Functions
* weekday is 0-6 for Mon-Sun
* yearday is 1-366
.. function:: mktime()
.. function:: mktime(date_time_tuple)
This is inverse function of localtime. It's argument is a full 8-tuple
which expresses a time as per localtime. It returns an integer which is
the number of seconds since Jan 1, 2000.
the number of seconds since the time epoch.
.. function:: sleep(seconds)

View File

@@ -358,13 +358,13 @@ Run WM8960 on a MIMXRT10xx_DEV board in secondary mode (default)::
sysclk_source=wm8960.SYSCLK_MCLK)
Record with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default)::
Record with a SparkFun WM8960 breakout board with Teensy in secondary mode (default)::
# Micro_python WM8960 Codec driver
#
# The breakout board uses a fixed 24MHz MCLK. Therefore the internal
# PLL must be used as sysclk, which is the master audio clock.
# The Sparkfun board has the WS pins for RX and TX connected on the
# The SparkFun board has the WS pins for RX and TX connected on the
# board. Therefore adc_sync must be set to sync_adc, to configure
# it's ADCLRC pin as input.
#
@@ -379,11 +379,11 @@ Record with a Sparkfun WM8960 breakout board with Teensy in secondary mode (defa
right_input=wm8960.INPUT_CLOSED)
Play with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default)::
Play with a SparkFun WM8960 breakout board with Teensy in secondary mode (default)::
# The breakout board uses a fixed 24MHz MCLK. Therefore the internal
# PLL must be used as sysclk, which is the master audio clock.
# The Sparkfun board has the WS pins for RX and TX connected on the
# The SparkFun board has the WS pins for RX and TX connected on the
# board. Therefore adc_sync must be set to sync_adc, to configure
# it's ADCLRC pin as input.

View File

@@ -22,9 +22,10 @@ Functions
Returns the thread id of the current thread, which is used to reference the thread.
.. function:: thread_analyze()
.. function:: thread_analyze(cpu)
Runs the Zephyr debug thread analyzer on the current thread and prints stack size statistics in the format:
Runs the Zephyr debug thread analyzer on the current thread on the given cpu
and prints stack size statistics in the format:
"``thread_name``-20s: STACK: unused ``available_stack_space`` usage ``stack_space_used``
/ ``stack_size`` (``percent_stack_space_used`` %); CPU: ``cpu_utilization`` %"
@@ -35,6 +36,9 @@ Functions
For more information, see documentation for Zephyr `thread analyzer
<https://docs.zephyrproject.org/latest/guides/debug_tools/thread-analyzer.html#thread-analyzer>`_.
Note that the ``cpu`` argument is only used in Zephyr v4.0.0 and
newer and ignored otherwise.
.. function:: shell_exec(cmd_in)
Executes the given command on an UART backend. This function can only be accessed if ``CONFIG_SHELL_BACKEND_SERIAL``

View File

@@ -188,6 +188,13 @@ Glossary
Most MicroPython boards make a REPL available over a UART, and this is
typically accessible on a host PC via USB.
small integer
MicroPython optimises the internal representation of integers such that
"small" values do not take up space on the heap, and calculations with
them do not require heap allocation. On most 32-bit ports, this
corresponds to values in the interval ``-2**30 <= x < 2**30``, but this
should be considered an implementation detail and not relied upon.
stream
Also known as a "file-like object". A Python object which provides
sequential read-write access to the underlying data. A stream object

View File

@@ -108,7 +108,7 @@ The full list of supported commands are:
**Note:** Instead of using the ``connect`` command, there are several
:ref:`pre-defined shortcuts <mpremote_shortcuts>` for common device paths. For
example the ``a0`` shortcut command is equivalent to
``connect /dev/ttyACM0`` (Linux), or ``c0`` for ``COM0`` (Windows).
``connect /dev/ttyACM0`` (Linux), or ``c1`` for ``COM1`` (Windows).
**Note:** The ``auto`` option will only detect USB serial ports, i.e. a serial
port that has an associated USB VID/PID (i.e. CDC/ACM or FTDI-style
@@ -234,6 +234,7 @@ The full list of supported commands are:
- ``rmdir <dirs...>`` to remove directories on the device
- ``touch <file..>`` to create the files (if they don't already exist)
- ``sha256sum <file..>`` to calculate the SHA256 sum of files
- ``tree [-vsh] <dirs...>`` to print a tree of the given directories
The ``cp`` command uses a convention where a leading ``:`` represents a remote
path. Without a leading ``:`` means a local path. This is based on the
@@ -264,6 +265,13 @@ The full list of supported commands are:
There is no supported way to undelete files removed by ``mpremote rm -r :``.
Please use with caution.
The ``tree`` command will print a tree of the given directories.
Using the ``--size/-s`` option will print the size of each file, or use
``--human/-h`` to use a more human readable format.
Note: Directory size is only printed when a non-zero size is reported by the device's filesystem.
The ``-v`` option can be used to include the name of the serial device in
the output.
All other commands implicitly assume the path is a remote path, but the ``:``
can be optionally used for clarity.
@@ -479,9 +487,16 @@ Shortcuts can be defined using the macro system. Built-in shortcuts are:
- ``cat``, ``edit``, ``ls``, ``cp``, ``rm``, ``mkdir``, ``rmdir``, ``touch``: Aliases for ``fs <sub-command>``
Additional shortcuts can be defined by in user-configuration files, which is
located at ``.config/mpremote/config.py``. This file should define a
dictionary named ``commands``. The keys of this dictionary are the shortcuts
Additional shortcuts can be defined in the user configuration file ``mpremote/config.py``,
located in the User Configuration Directory.
The correct location for each OS is determined using the ``platformdirs`` module.
This is typically:
- ``$XDG_CONFIG_HOME/mpremote/config.py``
- ``$HOME/.config/mpremote/config.py``
- ``$env:LOCALAPPDATA/mpremote/config.py``
The ``config.py``` file should define a dictionary named ``commands``. The keys of this dictionary are the shortcuts
and the values are either a string or a list-of-strings:
.. code-block:: python3

View File

@@ -246,6 +246,13 @@ There are certain limitations in the current implementation of the native code e
* Context managers are not supported (the ``with`` statement).
* Generators are not supported.
* If ``raise`` is used an argument must be supplied.
* The background scheduler (see `micropython.schedule`) is not run during
execution of native code.
* On targets with thrteading and the GIL, the GIL is not released during
execution of native code.
To mitigate the last two points, long running native functions should call
``time.sleep(0)`` periodically, which will run the scheduler and bounce the GIL.
The trade-off for the improved performance (roughly twice as fast as bytecode) is an
increase in compiled code size.

View File

@@ -135,6 +135,12 @@ Use the :mod:`machine.Timer` class::
tim = Timer(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2))
By default, timer callbacks run as soft IRQs so they can allocate but
are prone to GC jitter and delays. Pass ``hard=True`` to the ``Timer()``
constructor or ``init()`` method to run the callback in hard-IRQ context
instead. This reduces delay and jitter, but see :ref:`isr_rules` for the
restrictions that apply to hard-IRQ handlers.
.. _rp2_Pins_and_GPIO:

View File

@@ -650,6 +650,124 @@ Adafruit ItsyBitsy M0 Express :ref:`samd21_pinout_table`.
The board does not provide access to UART, I2C, SPI or DAC.
SparkFun Redboard Turbo assignment table
----------------------------------------
=== ==== ============ ==== ==== ====== ====== ====== ======
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
=== ==== ============ ==== ==== ====== ====== ====== ======
2 PA02 A0 2 0 - - - -
40 PB08 A1 8 2 - 4/0 4/0 -
41 PB09 A2 9 3 - 4/1 4/1 -
4 PA04 A3 4 4 - 0/0 0/0 -
5 PA05 A4 5 5 - 0/1 0/1 -
34 PB02 A5 2 10 - 5/0 6/0 -
11 PA11 D0 11 19 0/3 2/3 1/1 0/3
10 PA10 D1 10 18 0/2 2/2 1/0 0/2
14 PA14 D2 14 - 2/2 4/2 3/0 0/4
9 PA09 D3 9 17 0/1 2/1 0/1 1/3
8 PA08 D4 - 16 0/0 2/0 0/0 1/2
15 PA15 D5 15 - 2/3 4/3 3/1 0/5
20 PA20 D6 4 - 5/2 3/2 7/0 0/4
21 PA21 D7 5 - 5/3 3/3 7/1 0/7
6 PA06 D8 6 6 - 0/2 1/0 -
7 PA07 D9 7 7 - 0/3 1/1 -
11 PA11 RX 11 19 0/3 2/3 1/1 0/3
10 PA10 TX 10 18 0/2 2/2 1/0 0/2
3 PA03 AREF 3 1 - - - -
18 PA18 D10 2 - 1/2 3/2 3/0 0/2
16 PA16 D11 0 - 1/0 3/0 2/0 0/6
19 PA19 D12 3 - 1/3 3/3 3/1 0/3
17 PA17 D13 1 - 1/1 3/1 2/1 0/7
13 PA13 FLASH_CS 13 - 2/1 4/1 2/0 0/7
35 PB03 FLASH_MISO 3 11 - 5/1 6/1 -
54 PB22 FLASH_MOSI 6 - - 5/2 7/0 -
55 PB23 FLASH_SCK 7 - - 5/3 7/1 -
31 PA31 LED_RX 11 - - 1/3 1/1 -
27 PA27 LED_TX 15 - - - - -
12 PA12 MISO 12 - 2/0 4/0 2/0 0/6
42 PB10 MOSI 10 - - 4/2 5/0 0/4
30 PA30 NEOPIXEL 10 - - 1/2 1/0 -
43 PB11 SCK 11 - - 4/3 5/1 0/5
23 PA23 SCL 7 - 3/1 5/1 4/1 0/5
22 PA22 SDA 6 - 3/0 5/0 4/0 0/4
30 PA30 SWCLK 10 - - 1/2 1/0 -
31 PA31 SWDIO 11 - - 1/3 1/1 -
24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2
25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3
0 PA00 0 - - 1/0 2/0 -
1 PA01 1 - - 1/1 2/1 -
28 PA28 8 - - - - -
=== ==== ============ ==== ==== ====== ====== ====== ======
For the definition of the table columns see the explanation at the table for
Adafruit ItsyBitsy M0 Express :ref:`samd21_pinout_table`.
The default devices at the board are:
- UART 0 at pins PA11/PA10, labelled RX/TX
- I2C 3 at pins PA22/PA23, labelled SDA/SCL
- SPI 4 at pins PB10/PA12/PB11, labelled MISO, MOSI and SCK
- DAC output on pin PA02, labelled A0
SparkFun SAMD21 Dev Breakout assignment table
---------------------------------------------
=== ==== ============ ==== ==== ====== ====== ====== ======
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
=== ==== ============ ==== ==== ====== ====== ====== ======
2 PA02 A0 2 0 - - - -
40 PB08 A1 8 2 - 4/0 4/0 -
41 PB09 A2 9 3 - 4/1 4/1 -
4 PA04 A3 4 4 - 0/0 0/0 -
5 PA05 A4 5 5 - 0/1 0/1 -
34 PB02 A5 2 10 - 5/0 6/0 -
11 PA11 D0 11 19 0/3 2/3 1/1 0/3
10 PA10 D1 10 18 0/2 2/2 1/0 0/2
14 PA14 D2 14 - 2/2 4/2 3/0 0/4
9 PA09 D3 9 17 0/1 2/1 0/1 1/3
8 PA08 D4 - 16 0/0 2/0 0/0 1/2
15 PA15 D5 15 - 2/3 4/3 3/1 0/5
20 PA20 D6 4 - 5/2 3/2 7/0 0/4
21 PA21 D7 5 - 5/3 3/3 7/1 0/7
6 PA06 D8 6 6 - 0/2 1/0 -
7 PA07 D9 7 7 - 0/3 1/1 -
11 PA11 RX 11 19 0/3 2/3 1/1 0/3
10 PA10 TX 10 18 0/2 2/2 1/0 0/2
3 PA03 AREF 3 1 - - - -
18 PA18 D10 2 - 1/2 3/2 3/0 0/2
16 PA16 D11 0 - 1/0 3/0 2/0 0/6
19 PA19 D12 3 - 1/3 3/3 3/1 0/3
17 PA17 D13 1 - 1/1 3/1 2/1 0/7
54 PB22 D30 6 - - 5/2 7/0 -
55 PB23 D31 7 - - 5/3 7/1 -
13 PA13 D38 13 - 2/1 4/1 2/0 0/7
35 PB03 LED_RX 3 11 - 5/1 6/1 -
27 PA27 LED_TX 15 - - - - -
12 PA12 MISO 12 - 2/0 4/0 2/0 0/6
42 PB10 MOSI 10 - - 4/2 5/0 0/4
43 PB11 SCK 11 - - 4/3 5/1 0/5
23 PA23 SCL 7 - 3/1 5/1 4/1 0/5
22 PA22 SDA 6 - 3/0 5/0 4/0 0/4
30 PA30 SWCLK 10 - - 1/2 1/0 -
31 PA31 SWDIO 11 - - 1/3 1/1 -
24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2
25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3
0 PA00 0 - - 1/0 2/0 -
1 PA01 1 - - 1/1 2/1 -
28 PA28 8 - - - - -
=== ==== ============ ==== ==== ====== ====== ====== ======
For the definition of the table columns see the explanation at the table for
Adafruit ItsyBitsy M0 Express :ref:`samd21_pinout_table`.
The default devices at the board are:
- UART 0 at pins PA11/PA10, labelled RX/TX
- I2C 3 at pins PA22/PA23, labelled SDA/SCL
- SPI 4 at pins PB10/PA12/PB11, labelled MISO, MOSI and SCK
- DAC output on pin PA02, labelled A0
SAMD21 Xplained PRO pin assignment table
----------------------------------------
@@ -892,7 +1010,7 @@ Default pin assignments:
There seems to be no default pin assignment for this board.
Sparkfun SAMD51 Thing Plus pin assignment table
SparkFun SAMD51 Thing Plus pin assignment table
------------------------------------------------
=== ==== ============ ==== ==== ==== ====== ====== ===== ===== =====

View File

@@ -56,6 +56,21 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
switch = Pin(("gpioc", 6), Pin.IN) # create input pin for a switch
switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
PWM
---
Use the :ref:`machine.PWM <machine.PWM>` class::
from machine import PWM
pwm = PWM(("pwm0", 0), freq=3921568, duty_ns=200, invert=True) # create pwm on PWM0
print(pwm) # print pwm
print(pwm.duty_ns()) # print pwm duty cycle in nanoseconds
pwm.duty_ns(255) # set new pwm duty cycle in nanoseconds
pwm.deinit()
Hardware I2C bus
----------------
@@ -138,6 +153,8 @@ Use the :ref:`zephyr.FlashArea <zephyr.FlashArea>` class to support filesystem::
f.write('Hello world') # write to the file
print(open('/flash/hello.txt').read()) # print contents of the file
The FlashAreas' IDs that are available are listed in the FlashArea module, as ID_*.
Sensor
------

View File

@@ -31,7 +31,7 @@ With your serial program open (PuTTY, screen, picocom, etc) you may see a
blank screen with a flashing cursor. Press Enter (or reset the board) and
you should be presented with the following text::
*** Booting Zephyr OS build v3.7.0 ***
*** Booting Zephyr OS build v4.0.0 ***
MicroPython v1.24.0-preview.179.g5b85b24bd on 2024-08-05; zephyr-frdm_k64f with mk64f12
Type "help()" for more information.
>>>

View File

@@ -46,6 +46,7 @@ typedef struct _mp_qspi_proto_t {
int (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
int (*read_cmd)(void *self, uint8_t cmd, size_t len, uint32_t *dest);
int (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, uint8_t num_dummy, size_t len, uint8_t *dest);
int (*direct_read)(void *self, uint32_t addr, size_t len, uint8_t *dest); // can be NULL if direct read not supported
} mp_qspi_proto_t;
typedef struct _mp_soft_qspi_obj_t {

View File

@@ -1,17 +0,0 @@
CYW43xx WiFi SoC driver
=======================
This is a driver for the CYW43xx WiFi SoC.
There are four layers to the driver:
1. SDIO bus interface, provided by the host device/system.
2. Low-level CYW43xx interface, managing the bus, control messages, Ethernet
frames and asynchronous events. Includes download of SoC firmware. The
header file `cyw43_ll.h` defines the interface to this layer.
3. Mid-level CYW43xx control, to control and set WiFi parameters and manage
events. See `cyw43_ctrl.c`.
4. TCP/IP bindings to lwIP. See `cyw43_lwip.c`.

View File

@@ -1,304 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019-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 <stdio.h>
#include <string.h>
#include "py/runtime.h"
#include "py/mphal.h"
#include "extmod/mpbthci.h"
#if MICROPY_PY_NETWORK_CYW43
#include "lib/cyw43-driver/src/cyw43_config.h"
#include "lib/cyw43-driver/firmware/cyw43_btfw_4343A1.h"
// 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 machine_uart_obj_t mp_bluetooth_hci_uart_obj;
static void cywbt_wait_cts_low(void) {
mp_hal_pin_config(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
for (int i = 0; i < 200; ++i) {
if (mp_hal_pin_read(CYW43_PIN_BT_CTS) == 0) {
break;
}
mp_hal_delay_ms(1);
}
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) {
mp_bluetooth_hci_uart_write((void *)buf, len);
for (int c, i = 0; i < 6; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
mp_event_wait_indefinite();
}
buf[i] = c;
}
// expect a command complete event (event 0x0e)
if (buf[0] != 0x04 || buf[1] != 0x0e) {
printf("unknown response: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
return -1;
}
/*
if buf[3:6] != cmd[:3]:
print('response doesn\'t match cmd:', cmd, ev)
return b''
*/
int sz = buf[2] - 3;
for (int c, i = 0; i < sz; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
mp_event_wait_indefinite();
}
buf[i] = c;
}
return 0;
}
static int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) {
uint8_t *buf = mp_bluetooth_hci_cmd_buf;
buf[0] = 0x01;
buf[1] = ocf;
buf[2] = ogf << 2 | ocf >> 8;
buf[3] = param_len;
if (param_len) {
memcpy(buf + 4, param_buf, param_len);
}
return cywbt_hci_cmd_raw(4 + param_len, buf);
}
static void put_le16(uint8_t *buf, uint16_t val) {
buf[0] = val;
buf[1] = val >> 8;
}
static void put_le32(uint8_t *buf, uint32_t val) {
buf[0] = val;
buf[1] = val >> 8;
buf[2] = val >> 16;
buf[3] = val >> 24;
}
static int cywbt_set_baudrate(uint32_t baudrate) {
uint8_t buf[6];
put_le16(buf, 0);
put_le32(buf + 2, baudrate);
return cywbt_hci_cmd(0x3f, 0x18, 6, buf);
}
// download firmware
static int cywbt_download_firmware(const uint8_t *firmware) {
cywbt_hci_cmd(0x3f, 0x2e, 0, NULL);
bool last_packet = false;
while (!last_packet) {
uint8_t *buf = mp_bluetooth_hci_cmd_buf;
memcpy(buf + 1, firmware, 3);
firmware += 3;
last_packet = buf[1] == 0x4e;
if (buf[2] != 0xfc) {
printf("fail1 %02x\n", buf[2]);
break;
}
uint8_t len = buf[3];
memcpy(buf + 4, firmware, len);
firmware += len;
buf[0] = 1;
cywbt_hci_cmd_raw(4 + len, buf);
if (buf[0] != 0) {
printf("fail3 %02x\n", buf[0]);
break;
}
}
// RF switch must select high path during BT patch boot
#if MICROPY_HW_ENABLE_RF_SWITCH
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
// 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);
cywbt_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY);
mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY);
return 0;
}
int mp_bluetooth_hci_controller_init(void) {
// This is called immediately after the UART is initialised during stack initialisation.
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(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(CYW43_PIN_BT_REG_ON);
mp_bluetooth_hci_uart_set_baudrate(115200);
mp_hal_delay_ms(100);
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);
#ifdef MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE
// Change baudrate
cywbt_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE);
mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE);
#endif
cywbt_download_firmware((const uint8_t *)&cyw43_btfw_4343A1[0]);
// Reset
cywbt_hci_cmd(0x03, 0x0003, 0, NULL);
// Set BD_ADDR (sent as little endian)
uint8_t bdaddr[6];
mp_hal_get_mac(MP_HAL_MAC_BDADDR, bdaddr);
buf[0] = bdaddr[5];
buf[1] = bdaddr[4];
buf[2] = bdaddr[3];
buf[3] = bdaddr[2];
buf[4] = bdaddr[1];
buf[5] = bdaddr[0];
cywbt_hci_cmd(0x3f, 0x0001, 6, buf);
// Set local name
// memset(buf, 0, 248);
// memcpy(buf, "PYBD-BLE", 8);
// 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");
// HCI_Write_LE_Host_Support
cywbt_hci_cmd(3, 109, 2, (const uint8_t *)"\x01\x00");
#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(CYW43_PIN_BT_REG_ON);
return 0;
}
#ifdef CYW43_PIN_BT_DEV_WAKE
static uint32_t bt_sleep_ticks;
#endif
int mp_bluetooth_hci_controller_sleep_maybe(void) {
#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(CYW43_PIN_BT_DEV_WAKE); // let sleep
}
}
#endif
return 0;
}
bool mp_bluetooth_hci_controller_woken(void) {
#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;
if (host_wake != last_host_wake) {
printf("HOST_WAKE change %d -> %d\n", last_host_wake, host_wake);
last_host_wake = host_wake;
}
*/
return host_wake;
#else
return true;
#endif
}
int mp_bluetooth_hci_controller_wakeup(void) {
#ifdef CYW43_PIN_BT_DEV_WAKE
bt_sleep_ticks = mp_hal_ticks_ms();
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
}
#endif
return 0;
}
#endif

View File

@@ -72,7 +72,7 @@ int esp_hosted_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_
// Receive HCI event packet, initially reading 3 bytes (HCI Event, Event code, Plen).
for (mp_uint_t start = mp_hal_ticks_ms(), size = 3, i = 0; i < size;) {
while (!mp_bluetooth_hci_uart_any()) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_ms(1);
// Timeout.
if ((mp_hal_ticks_ms() - start) > HCI_COMMAND_TIMEOUT) {
error_printf("timeout waiting for HCI packet\n");
@@ -126,7 +126,7 @@ int mp_bluetooth_hci_controller_init(void) {
if (mp_bluetooth_hci_uart_any()) {
mp_bluetooth_hci_uart_readchar();
}
MICROPY_EVENT_POLL_HOOK
mp_event_wait_ms(1);
}
#ifdef MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY

View File

@@ -243,7 +243,7 @@ static int esp_hosted_request(CtrlMsgId msg_id, void *ctrl_payload) {
static CtrlMsg *esp_hosted_response(CtrlMsgId msg_id, uint32_t timeout) {
CtrlMsg *ctrl_msg = NULL;
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_event_wait_ms(10)) {
if (!esp_hosted_stack_empty(&esp_state.stack)) {
ctrl_msg = esp_hosted_stack_pop(&esp_state.stack, true);
if (ctrl_msg->msg_id == msg_id) {
@@ -264,8 +264,6 @@ static CtrlMsg *esp_hosted_response(CtrlMsgId msg_id, uint32_t timeout) {
if ((mp_hal_ticks_ms() - start) >= timeout) {
return NULL;
}
MICROPY_EVENT_POLL_HOOK
}
// If message type is a response, check the response struct's return value.

View File

@@ -197,6 +197,10 @@ void mp_spiflash_init(mp_spiflash_t *self) {
} else {
uint8_t num_dummy = MICROPY_HW_SPIFLASH_QREAD_NUM_DUMMY(self);
self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT, num_dummy);
if (self->config->bus.u_qspi.proto->direct_read != NULL) {
// A bus with a custom read function should not have any further initialisation done.
return;
}
}
mp_spiflash_acquire_bus(self);
@@ -318,6 +322,10 @@ int mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *de
if (len == 0) {
return 0;
}
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI && c->bus.u_qspi.proto->direct_read != NULL) {
return c->bus.u_qspi.proto->direct_read(c->bus.u_qspi.data, addr, len, dest);
}
mp_spiflash_acquire_bus(self);
int ret = mp_spiflash_read_data(self, addr, len, dest);
mp_spiflash_release_bus(self);

View File

@@ -114,13 +114,13 @@ void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
mode = NINA_GPIO_OUTPUT;
self->is_output = true;
} else {
mp_raise_ValueError("only Pin.OUT and Pin.IN are supported for this pin");
mp_raise_ValueError(MP_ERROR_TEXT("only Pin.OUT and Pin.IN are supported for this pin"));
}
if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
uint8_t buf[] = {pin_map[self->id], mode};
if (mode == NINA_GPIO_OUTPUT) {
if (NINA_GPIO_IS_INPUT_ONLY(self->id)) {
mp_raise_ValueError("only Pin.IN is supported for this pin");
mp_raise_ValueError(MP_ERROR_TEXT("only Pin.IN is supported for this pin"));
}
machine_pin_ext_set(self, value);
}

View File

@@ -50,8 +50,8 @@
#define OCF_SET_EVENT_MASK (0x0001)
#define OCF_RESET (0x0003)
#define error_printf(...) // mp_printf(&mp_plat_print, "nina_bt_hci.c: " __VA_ARGS__)
#define debug_printf(...) // mp_printf(&mp_plat_print, "nina_bt_hci.c: " __VA_ARGS__)
#define error_printf(...) // mp_printf(&mp_plat_print, "nina_bthci_uart.c: " __VA_ARGS__)
#define debug_printf(...) // mp_printf(&mp_plat_print, "nina_bthci_uart.c: " __VA_ARGS__)
// Provided by the port, and also possibly shared with the stack.
extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];

View File

@@ -79,12 +79,9 @@ def decode_name(payload):
def decode_services(payload):
services = []
for u in decode_field(payload, _ADV_TYPE_UUID16_COMPLETE):
services.append(bluetooth.UUID(struct.unpack("<h", u)[0]))
for u in decode_field(payload, _ADV_TYPE_UUID32_COMPLETE):
services.append(bluetooth.UUID(struct.unpack("<d", u)[0]))
for u in decode_field(payload, _ADV_TYPE_UUID128_COMPLETE):
services.append(bluetooth.UUID(u))
for code in (_ADV_TYPE_UUID16_COMPLETE, _ADV_TYPE_UUID32_COMPLETE, _ADV_TYPE_UUID128_COMPLETE):
for u in decode_field(payload, code):
services.append(bluetooth.UUID(u))
return services

View File

@@ -8,7 +8,7 @@ MOD = btree_$(ARCH)
SRC = btree_c.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin, rv32imc)
ARCH = x64
ARCH ?= x64
BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx
BERKELEY_DB_CONFIG_FILE ?= \"extmod/berkeley-db/berkeley_db_config_port.h\"
@@ -32,6 +32,18 @@ SRC += $(addprefix $(realpath $(BTREE_DIR))/,\
mpool/mpool.c \
)
ifeq ($(ARCH),xtensa)
MPY_EXTERN_SYM_FILE=$(MPY_DIR)/ports/esp8266/boards/eagle.rom.addr.v6.ld
endif
# Use our own errno implementation if Picolibc is used
CFLAGS += -D__PICOLIBC_ERRNO_FUNCTION=__errno
ifeq ($(ARCH),armv6m)
# Link with libgcc.a for division helper functions
LINK_RUNTIME = 1
endif
include $(MPY_DIR)/py/dynruntime.mk
# btree needs gnu99 defined

View File

@@ -8,6 +8,17 @@ MOD = deflate_$(ARCH)
SRC = deflate.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin, rv32imc)
ARCH = x64
ARCH ?= x64
ifeq ($(ARCH),armv6m)
# Link with libgcc.a for division helper functions
LINK_RUNTIME = 1
endif
ifeq ($(ARCH),xtensa)
# Link with libm.a and libgcc.a from the toolchain
LINK_RUNTIME = 1
MPY_EXTERN_SYM_FILE=$(MPY_DIR)/ports/esp8266/boards/eagle.rom.addr.v6.ld
endif
include $(MPY_DIR)/py/dynruntime.mk

View File

@@ -8,6 +8,15 @@ MOD = framebuf_$(ARCH)
SRC = framebuf.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
ARCH ?= x64
ifeq ($(ARCH),armv6m)
# Link with libgcc.a for division helper functions
LINK_RUNTIME = 1
endif
ifeq ($(ARCH),xtensa)
MPY_EXTERN_SYM_FILE=$(MPY_DIR)/ports/esp8266/boards/eagle.rom.addr.v6.ld
endif
include $(MPY_DIR)/py/dynruntime.mk

View File

@@ -4,6 +4,9 @@
#include "py/dynruntime.h"
#if !defined(__linux__)
void *memcpy(void *dst, const void *src, size_t n) {
return mp_fun_table.memmove_(dst, src, n);
}
void *memset(void *s, int c, size_t n) {
return mp_fun_table.memset_(s, c, n);
}

View File

@@ -8,6 +8,15 @@ MOD = random_$(ARCH)
SRC = random.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin, rv32imc)
ARCH = x64
ARCH ?= x64
ifeq ($(ARCH),xtensa)
MPY_EXTERN_SYM_FILE=$(MPY_DIR)/ports/esp8266/boards/eagle.rom.addr.v6.ld
endif
ifeq ($(ARCH),$(filter $(ARCH),armv6m armv7m))
# Link with libm.a for soft-float helper functions
LINK_RUNTIME = 1
endif
include $(MPY_DIR)/py/dynruntime.mk

View File

@@ -10,4 +10,9 @@ SRC = re.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin, rv32imc)
ARCH = x64
ifeq ($(ARCH),armv6m)
# Link with libgcc.a for division helper functions
LINK_RUNTIME = 1
endif
include $(MPY_DIR)/py/dynruntime.mk

View File

@@ -23,7 +23,7 @@ PIO_RX_PIN = Pin(3, Pin.IN, Pin.PULL_UP)
@asm_pio(
autopush=True,
push_thresh=8,
in_shiftdir=rp2.PIO.SHIFT_RIGHT,
in_shiftdir=PIO.SHIFT_RIGHT,
fifo_join=PIO.JOIN_RX,
)
def uart_rx_mini():
@@ -42,7 +42,7 @@ def uart_rx_mini():
@asm_pio(
in_shiftdir=rp2.PIO.SHIFT_RIGHT,
in_shiftdir=PIO.SHIFT_RIGHT,
)
def uart_rx():
# fmt: off

View File

@@ -86,12 +86,12 @@ static void example_AdvancedTimer_print(const mp_print_t *print, mp_obj_t self_i
mp_uint_t elapsed = mp_obj_get_int(example_Timer_time(self_in));
// We'll make all representations print at least the class name.
mp_printf(print, "%q()", MP_QSTR_AdvancedTimer);
mp_printf(print, "%q()", (qstr)MP_QSTR_AdvancedTimer);
// Decide what else to print based on print kind.
if (kind == PRINT_STR) {
// For __str__, let's attempt to make it more readable.
mp_printf(print, " # created %d seconds ago", elapsed / 1000);
mp_printf(print, " # created %d seconds ago", (int)(elapsed / 1000));
}
}

View File

@@ -163,9 +163,16 @@ def run_until_complete(main_task=None):
# A task waiting on _task_queue; "ph_key" is time to schedule task at
dt = max(0, ticks_diff(t.ph_key, ticks()))
elif not _io_queue.map:
# No tasks can be woken so finished running
# No tasks can be woken
cur_task = None
return
if not main_task or not main_task.state:
# no main_task, or main_task is done so finished running
return
# At this point, there is theoretically nothing that could wake the
# scheduler, but it is not allowed to exit either. We keep the code
# running so that a hypothetical debugger (or other such meta-process)
# can get a view of what is happening and possibly abort.
dt = 3
# print('(poll {})'.format(dt), len(_io_queue.map))
_io_queue.wait_io_event(dt)
@@ -187,31 +194,33 @@ def run_until_complete(main_task=None):
except excs_all as er:
# Check the task is not on any event queue
assert t.data is None
# This task is done, check if it's the main task and then loop should stop
if t is main_task:
# If it's the main task, it is considered as awaited by the caller
awaited = t is main_task
if awaited:
cur_task = None
if isinstance(er, StopIteration):
return er.value
raise er
if not isinstance(er, StopIteration):
t.state = False
raise er
if t.state is None:
t.state = False
if t.state:
# Task was running but is now finished.
waiting = False
if t.state is True:
# "None" indicates that the task is complete and not await'ed on (yet).
t.state = None
t.state = False if awaited else None
elif callable(t.state):
# The task has a callback registered to be called on completion.
t.state(t, er)
t.state = False
waiting = True
awaited = True
else:
# Schedule any other tasks waiting on the completion of this task.
while t.state.peek():
_task_queue.push(t.state.pop())
waiting = True
awaited = True
# "False" indicates that the task is complete and has been await'ed on.
t.state = False
if not waiting and not isinstance(er, excs_stop):
if not awaited and not isinstance(er, excs_stop):
# An exception ended this detached task, so queue it for later
# execution to handle the uncaught exception if no other task retrieves
# the exception in the meantime (this is handled by Task.throw).
@@ -229,6 +238,9 @@ def run_until_complete(main_task=None):
_exc_context["exception"] = exc
_exc_context["future"] = t
Loop.call_exception_handler(_exc_context)
# If it's the main task then the loop should stop
if t is main_task:
return er.value
# Create a new task from a coroutine and run it until it finishes

View File

@@ -705,12 +705,12 @@ int mp_bluetooth_init(void) {
return 0;
}
void mp_bluetooth_deinit(void) {
int mp_bluetooth_deinit(void) {
DEBUG_printf("mp_bluetooth_deinit\n");
// Nothing to do if not initialised.
if (!MP_STATE_PORT(bluetooth_btstack_root_pointers)) {
return;
return 0;
}
mp_bluetooth_gap_advertise_stop();
@@ -737,6 +737,9 @@ void mp_bluetooth_deinit(void) {
deinit_stack();
DEBUG_printf("mp_bluetooth_deinit: complete\n");
bool timeout = mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_TIMEOUT;
return timeout ? MP_ETIMEDOUT : 0;
}
bool mp_bluetooth_is_active(void) {

View File

@@ -0,0 +1,126 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2025 Damien P. George, 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_EXTMOD_CYW43_CONFIG_COMMON_H
#define MICROPY_INCLUDED_EXTMOD_CYW43_CONFIG_COMMON_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 "py/runtime.h"
#include "extmod/modnetwork.h"
#include "lwip/apps/mdns.h"
#include "pendsv.h"
// This file is included at the top of port-specific cyw43_configport.h files,
// and holds the MicroPython-specific but non-port-specific parts.
//
// It's included into both MicroPython sources and the lib/cyw43-driver sources.
#define CYW43_IOCTL_TIMEOUT_US (1000000)
#define CYW43_NETUTILS (1)
#define CYW43_PRINTF(...) mp_printf(MP_PYTHON_PRINTER, __VA_ARGS__)
#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_data
#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_MAC_BDADDR MP_HAL_MAC_BDADDR
#define cyw43_hal_ticks_us mp_hal_ticks_us
#define cyw43_hal_ticks_ms mp_hal_ticks_ms
#define cyw43_hal_pin_obj_t mp_hal_pin_obj_t
#define cyw43_hal_pin_config mp_hal_pin_config
#define cyw43_hal_pin_read mp_hal_pin_read
#define cyw43_hal_pin_low mp_hal_pin_low
#define cyw43_hal_pin_high mp_hal_pin_high
#define cyw43_hal_get_mac mp_hal_get_mac
#define cyw43_hal_get_mac_ascii mp_hal_get_mac_ascii
#define cyw43_hal_generate_laa_mac mp_hal_generate_laa_mac
#define cyw43_schedule_internal_poll_dispatch(func) pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, func)
// Note: this function is only called if CYW43_POST_POLL_HOOK is defined in cyw43_configport.h
void cyw43_post_poll_hook(void);
#ifdef MICROPY_EVENT_POLL_HOOK
// Older style hook macros on some ports
#define CYW43_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK
#else
// Newer style hooks on other ports
#define CYW43_EVENT_POLL_HOOK mp_event_handle_nowait()
#endif
static inline void cyw43_delay_us(uint32_t us) {
uint32_t start = mp_hal_ticks_us();
while (mp_hal_ticks_us() - start < us) {
}
}
static inline void cyw43_delay_ms(uint32_t ms) {
// PendSV may be disabled via CYW43_THREAD_ENTER, so this delay is a busy loop.
uint32_t us = ms * 1000;
uint32_t start = mp_hal_ticks_us();
while (mp_hal_ticks_us() - start < us) {
CYW43_EVENT_POLL_HOOK;
}
}
#if LWIP_MDNS_RESPONDER == 1
// Hook for any additional TCP/IP initialization than needs to be done.
// Called after the netif specified by `itf` has been set up.
#ifndef CYW43_CB_TCPIP_INIT_EXTRA
#define CYW43_CB_TCPIP_INIT_EXTRA(self, itf) mdns_resp_add_netif(&self->netif[itf], mod_network_hostname_data)
#endif
// Hook for any additional TCP/IP deinitialization than needs to be done.
// Called before the netif specified by `itf` is removed.
#ifndef CYW43_CB_TCPIP_DEINIT_EXTRA
#define CYW43_CB_TCPIP_DEINIT_EXTRA(self, itf) mdns_resp_remove_netif(&self->netif[itf])
#endif
#endif
#endif // MICROPY_INCLUDED_EXTMOD_CYW43_CONFIG_COMMON_H

View File

@@ -11,6 +11,7 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/machine_adc_block.c
${MICROPY_EXTMOD_DIR}/machine_bitstream.c
${MICROPY_EXTMOD_DIR}/machine_i2c.c
${MICROPY_EXTMOD_DIR}/machine_i2c_target.c
${MICROPY_EXTMOD_DIR}/machine_i2s.c
${MICROPY_EXTMOD_DIR}/machine_mem.c
${MICROPY_EXTMOD_DIR}/machine_pulse.c

View File

@@ -6,6 +6,7 @@ SRC_EXTMOD_C += \
extmod/machine_adc_block.c \
extmod/machine_bitstream.c \
extmod/machine_i2c.c \
extmod/machine_i2c_target.c \
extmod/machine_i2s.c \
extmod/machine_mem.c \
extmod/machine_pinbase.c \
@@ -206,7 +207,7 @@ endif
ifeq ($(MICROPY_VFS_LFS2),1)
CFLAGS_EXTMOD += -DMICROPY_VFS_LFS2=1
CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT
CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT -DLFS2_DEFINES=extmod/littlefs-include/lfs2_defines.h
SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\
lfs2.c \
lfs2_util.c \
@@ -504,7 +505,7 @@ ESP_HOSTED_SRC_C = $(addprefix $(ESP_HOSTED_DIR)/,\
)
ifeq ($(MICROPY_PY_BLUETOOTH),1)
ESP_HOSTED_SRC_C += $(ESP_HOSTED_DIR)/esp_hosted_bthci.c
ESP_HOSTED_SRC_C += $(ESP_HOSTED_DIR)/esp_hosted_bthci_uart.c
endif
# Include the protobuf-c support functions

View File

@@ -0,0 +1,12 @@
#ifndef LFS2_DEFINES_H
#define LFS2_DEFINES_H
#include "py/mpconfig.h"
#if MICROPY_PY_DEFLATE
// We reuse the CRC32 implementation from uzlib to save a few bytes
#include "lib/uzlib/uzlib.h"
#define LFS2_CRC(crc, buffer, size) uzlib_crc32(buffer, size, crc)
#endif
#endif

View File

@@ -28,6 +28,9 @@
#include "py/mpconfig.h"
// This is needed to access `next_timeout` via `sys_timeouts_get_next_timeout()`.
#define LWIP_TESTMODE 1
// This sys-arch protection is not needed.
// Ports either protect lwIP code with flags, or run it at PendSV priority.
#define SYS_ARCH_DECL_PROTECT(lev) do { } while (0)

424
extmod/machine_i2c_target.c Normal file
View File

@@ -0,0 +1,424 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2025 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"
#if MICROPY_PY_MACHINE_I2C_TARGET
#include "extmod/modmachine.h"
#include "shared/runtime/mpirq.h"
enum {
// Events exposed to Python.
I2C_TARGET_IRQ_ADDR_MATCH_READ = 1 << 0,
I2C_TARGET_IRQ_ADDR_MATCH_WRITE = 1 << 1,
I2C_TARGET_IRQ_READ_REQ = 1 << 2,
I2C_TARGET_IRQ_WRITE_REQ = 1 << 3,
I2C_TARGET_IRQ_END_READ = 1 << 4,
I2C_TARGET_IRQ_END_WRITE = 1 << 5,
// Internal event, not exposed to Python.
I2C_TARGET_IRQ_MEM_ADDR_MATCH = 1 << 6,
};
// Define the IRQs that require a hard interrupt.
#define I2C_TARGET_IRQ_ALL_HARD ( \
I2C_TARGET_IRQ_ADDR_MATCH_READ \
| I2C_TARGET_IRQ_ADDR_MATCH_WRITE \
| I2C_TARGET_IRQ_READ_REQ \
| I2C_TARGET_IRQ_WRITE_REQ \
)
enum {
STATE_INACTIVE,
STATE_IDLE,
STATE_ADDR_MATCH_READ,
STATE_ADDR_MATCH_WRITE,
STATE_MEM_ADDR_SELECT,
STATE_READING,
STATE_WRITING,
};
typedef struct _machine_i2c_target_data_t {
uint8_t state;
uint8_t mem_addr_count;
uint8_t mem_addrsize;
uint32_t mem_addr_last;
uint32_t mem_addr;
uint32_t mem_len;
uint8_t *mem_buf;
} machine_i2c_target_data_t;
typedef struct _machine_i2c_target_irq_obj_t {
mp_irq_obj_t base;
uint32_t flags;
uint32_t trigger;
} machine_i2c_target_irq_obj_t;
// The port must provide implementations of these low-level I2C target functions.
static void mp_machine_i2c_target_event_callback(machine_i2c_target_irq_obj_t *irq);
// Read up to N bytes, and return the number of bytes read.
static size_t mp_machine_i2c_target_read_bytes(machine_i2c_target_obj_t *self, size_t len, uint8_t *buf);
// Write (or buffer) N bytes, and return the number of bytes written/buffered.
static size_t mp_machine_i2c_target_write_bytes(machine_i2c_target_obj_t *self, size_t len, const uint8_t *buf);
// Configure the given events to trigger an interrupt.
static void mp_machine_i2c_target_irq_config(machine_i2c_target_obj_t *self, unsigned int trigger);
static mp_obj_t mp_machine_i2c_target_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
static void mp_machine_i2c_target_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
static void mp_machine_i2c_target_deinit(machine_i2c_target_obj_t *self);
static const mp_irq_methods_t machine_i2c_target_irq_methods;
static machine_i2c_target_data_t machine_i2c_target_data[MICROPY_PY_MACHINE_I2C_TARGET_MAX];
// Needed to retain a root pointer to the memory object.
MP_REGISTER_ROOT_POINTER(mp_obj_t machine_i2c_target_mem_obj[MICROPY_PY_MACHINE_I2C_TARGET_MAX]);
// Needed to retain a root pointer to the IRQ object.
MP_REGISTER_ROOT_POINTER(void *machine_i2c_target_irq_obj[MICROPY_PY_MACHINE_I2C_TARGET_MAX]);
static bool handle_event(machine_i2c_target_data_t *data, unsigned int trigger) {
unsigned int id = data - &machine_i2c_target_data[0];
if (trigger & I2C_TARGET_IRQ_MEM_ADDR_MATCH) {
data->mem_addr_last = data->mem_addr;
}
machine_i2c_target_irq_obj_t *irq = MP_STATE_PORT(machine_i2c_target_irq_obj[id]);
if (irq != NULL && (trigger & irq->trigger)) {
irq->flags = trigger & irq->trigger;
mp_machine_i2c_target_event_callback(irq);
return true; // irq handled
}
return false; // irq not handled
}
static void machine_i2c_target_data_init(machine_i2c_target_data_t *data, mp_obj_t mem_obj, mp_int_t mem_addrsize) {
data->state = STATE_IDLE;
data->mem_addr_count = 0;
data->mem_addrsize = 0;
data->mem_addr_last = 0;
data->mem_addr = 0;
data->mem_len = 0;
data->mem_buf = NULL;
if (mem_obj != mp_const_none) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(mem_obj, &bufinfo, MP_BUFFER_RW);
if (mem_addrsize < 0 || mem_addrsize > 32 || mem_addrsize % 8 != 0) {
mp_raise_ValueError(MP_ERROR_TEXT("mem_addrsize must be 0, 8, 16, 24 or 32"));
}
data->mem_addrsize = mem_addrsize / 8;
data->mem_len = bufinfo.len;
data->mem_buf = bufinfo.buf;
}
}
static void machine_i2c_target_data_reset_helper(machine_i2c_target_data_t *data) {
if (data->state == STATE_READING) {
handle_event(data, I2C_TARGET_IRQ_END_READ);
} else if (data->state == STATE_ADDR_MATCH_WRITE || data->state == STATE_WRITING) {
handle_event(data, I2C_TARGET_IRQ_END_WRITE);
}
data->state = STATE_IDLE;
}
static void machine_i2c_target_data_addr_match(machine_i2c_target_data_t *data, bool read) {
machine_i2c_target_data_reset_helper(data);
if (read) {
handle_event(data, I2C_TARGET_IRQ_ADDR_MATCH_READ);
data->state = STATE_ADDR_MATCH_READ;
} else {
handle_event(data, I2C_TARGET_IRQ_ADDR_MATCH_WRITE);
data->state = STATE_ADDR_MATCH_WRITE;
}
}
static void machine_i2c_target_data_read_request(machine_i2c_target_obj_t *self, machine_i2c_target_data_t *data) {
// Let the user handle the read request.
bool event_handled = handle_event(data, I2C_TARGET_IRQ_READ_REQ);
if (data->mem_buf == NULL) {
data->state = STATE_READING;
if (!event_handled) {
// No data source, just write out a zero.
uint8_t val = 0;
mp_machine_i2c_target_write_bytes(self, 1, &val);
}
} else {
// Have a buffer.
if (data->state == STATE_MEM_ADDR_SELECT) {
// Got a short memory address.
data->mem_addr %= data->mem_len;
handle_event(data, I2C_TARGET_IRQ_MEM_ADDR_MATCH);
}
if (data->state != STATE_READING) {
data->state = STATE_READING;
}
uint8_t val = data->mem_buf[data->mem_addr++];
if (data->mem_addr >= data->mem_len) {
data->mem_addr = 0;
}
mp_machine_i2c_target_write_bytes(self, 1, &val);
}
}
static void machine_i2c_target_data_write_request(machine_i2c_target_obj_t *self, machine_i2c_target_data_t *data) {
// Let the user handle the write request.
bool event_handled = handle_event(data, I2C_TARGET_IRQ_WRITE_REQ);
if (data->mem_buf == NULL) {
data->state = STATE_WRITING;
if (!event_handled) {
// No data sink, just read and discard the incoming byte.
uint8_t buf = 0;
mp_machine_i2c_target_read_bytes(self, 1, &buf);
}
} else {
// Have a buffer.
uint8_t buf[4] = {0};
size_t n = mp_machine_i2c_target_read_bytes(self, sizeof(buf), &buf[0]);
for (size_t i = 0; i < n; ++i) {
uint8_t val = buf[i];
if (data->state == STATE_ADDR_MATCH_WRITE) {
data->state = STATE_MEM_ADDR_SELECT;
data->mem_addr = 0;
data->mem_addr_count = data->mem_addrsize;
}
if (data->state == STATE_MEM_ADDR_SELECT && data->mem_addr_count > 0) {
data->mem_addr = data->mem_addr << 8 | val;
--data->mem_addr_count;
if (data->mem_addr_count == 0) {
data->mem_addr %= data->mem_len;
handle_event(data, I2C_TARGET_IRQ_MEM_ADDR_MATCH);
}
} else {
if (data->state == STATE_MEM_ADDR_SELECT) {
data->state = STATE_WRITING;
}
data->mem_buf[data->mem_addr++] = val;
if (data->mem_addr >= data->mem_len) {
data->mem_addr = 0;
}
}
}
}
}
static inline void machine_i2c_target_data_restart_or_stop(machine_i2c_target_data_t *data) {
machine_i2c_target_data_reset_helper(data);
}
static inline void machine_i2c_target_data_stop(machine_i2c_target_data_t *data) {
machine_i2c_target_data_reset_helper(data);
}
// The port provides implementations of its bindings in this file.
#include MICROPY_PY_MACHINE_I2C_TARGET_INCLUDEFILE
static void machine_i2c_target_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
size_t index = mp_machine_i2c_target_get_index(self);
machine_i2c_target_data_t *data = &machine_i2c_target_data[index];
if (dest[0] == MP_OBJ_NULL) {
// Load attribute.
if (attr == MP_QSTR_memaddr) {
dest[0] = mp_obj_new_int(data->mem_addr_last);
} else {
// Continue lookup in locals_dict.
dest[1] = MP_OBJ_SENTINEL;
}
}
}
// I2CTarget.deinit()
static mp_obj_t machine_i2c_target_deinit(mp_obj_t self_in) {
machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
size_t index = mp_machine_i2c_target_get_index(self);
if (machine_i2c_target_data[index].state != STATE_INACTIVE) {
machine_i2c_target_data[index].state = STATE_INACTIVE;
mp_machine_i2c_target_deinit(self);
MP_STATE_PORT(machine_i2c_target_mem_obj[index]) = MP_OBJ_NULL;
MP_STATE_PORT(machine_i2c_target_irq_obj[index]) = NULL;
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_target_deinit_obj, machine_i2c_target_deinit);
// I2CTarget.readinto(buf)
static mp_obj_t machine_i2c_target_readinto(mp_obj_t self_in, mp_obj_t buf_in) {
machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
return MP_OBJ_NEW_SMALL_INT(mp_machine_i2c_target_read_bytes(self, bufinfo.len, bufinfo.buf));
}
static MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_target_readinto_obj, machine_i2c_target_readinto);
// I2CTarget.write(data)
static mp_obj_t machine_i2c_target_write(mp_obj_t self_in, mp_obj_t data_in) {
machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
return MP_OBJ_NEW_SMALL_INT(mp_machine_i2c_target_write_bytes(self, bufinfo.len, bufinfo.buf));
}
static MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_target_write_obj, machine_i2c_target_write);
static machine_i2c_target_irq_obj_t *machine_i2c_target_get_irq(machine_i2c_target_obj_t *self) {
// Get the IRQ object.
size_t index = mp_machine_i2c_target_get_index(self);
machine_i2c_target_irq_obj_t *irq = MP_STATE_PORT(machine_i2c_target_irq_obj[index]);
// Allocate the IRQ object if it doesn't already exist.
if (irq == NULL) {
irq = m_new_obj(machine_i2c_target_irq_obj_t);
irq->base.base.type = &mp_irq_type;
irq->base.methods = (mp_irq_methods_t *)&machine_i2c_target_irq_methods;
irq->base.parent = MP_OBJ_FROM_PTR(self);
irq->base.handler = mp_const_none;
irq->base.ishard = false;
MP_STATE_PORT(machine_i2c_target_irq_obj[index]) = irq;
}
return irq;
}
// I2CTarget.irq(handler=None, trigger=IRQ_END_READ|IRQ_END_WRITE, hard=False)
static mp_obj_t machine_i2c_target_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_handler, ARG_trigger, ARG_hard };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = I2C_TARGET_IRQ_END_READ | I2C_TARGET_IRQ_END_WRITE} },
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
};
machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
machine_i2c_target_irq_obj_t *irq = machine_i2c_target_get_irq(self);
if (n_args > 1 || kw_args->used != 0) {
// Update IRQ data.
mp_obj_t handler = args[ARG_handler].u_obj;
mp_uint_t trigger = args[ARG_trigger].u_int;
bool hard = args[ARG_hard].u_bool;
#if MICROPY_PY_MACHINE_I2C_TARGET_HARD_IRQ
if ((trigger & I2C_TARGET_IRQ_ALL_HARD) && !hard) {
mp_raise_ValueError(MP_ERROR_TEXT("hard IRQ required"));
}
#else
if (hard) {
mp_raise_ValueError(MP_ERROR_TEXT("hard IRQ unsupported"));
}
#endif
// Disable all IRQs while data is updated.
mp_machine_i2c_target_irq_config(self, 0);
// Update IRQ data.
irq->base.handler = handler;
irq->base.ishard = hard;
irq->flags = 0;
irq->trigger = trigger;
// Enable IRQ if a handler is given.
if (handler != mp_const_none && trigger != 0) {
mp_machine_i2c_target_irq_config(self, trigger);
}
}
return MP_OBJ_FROM_PTR(irq);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_target_irq_obj, 1, machine_i2c_target_irq);
static const mp_rom_map_elem_t machine_i2c_target_locals_dict_table[] = {
#if MICROPY_PY_MACHINE_I2C_TARGET_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_i2c_target_deinit_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2c_target_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2c_target_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_target_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2c_target_irq_obj) },
#if MICROPY_PY_MACHINE_I2C_TARGET_HARD_IRQ
{ MP_ROM_QSTR(MP_QSTR_IRQ_ADDR_MATCH_READ), MP_ROM_INT(I2C_TARGET_IRQ_ADDR_MATCH_READ) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_ADDR_MATCH_WRITE), MP_ROM_INT(I2C_TARGET_IRQ_ADDR_MATCH_WRITE) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_READ_REQ), MP_ROM_INT(I2C_TARGET_IRQ_READ_REQ) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_WRITE_REQ), MP_ROM_INT(I2C_TARGET_IRQ_WRITE_REQ) },
#endif
{ MP_ROM_QSTR(MP_QSTR_IRQ_END_READ), MP_ROM_INT(I2C_TARGET_IRQ_END_READ) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_END_WRITE), MP_ROM_INT(I2C_TARGET_IRQ_END_WRITE) },
};
static MP_DEFINE_CONST_DICT(machine_i2c_target_locals_dict, machine_i2c_target_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
machine_i2c_target_type,
MP_QSTR_I2CTarget,
MP_TYPE_FLAG_NONE,
make_new, mp_machine_i2c_target_make_new,
print, mp_machine_i2c_target_print,
attr, &machine_i2c_target_attr,
locals_dict, &machine_i2c_target_locals_dict
);
static mp_uint_t machine_i2c_target_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
size_t index = mp_machine_i2c_target_get_index(self);
machine_i2c_target_irq_obj_t *irq = MP_STATE_PORT(machine_i2c_target_irq_obj[index]);
mp_machine_i2c_target_irq_config(self, 0);
irq->flags = 0;
irq->trigger = new_trigger;
mp_machine_i2c_target_irq_config(self, new_trigger);
return 0;
}
static mp_uint_t machine_i2c_target_irq_info(mp_obj_t self_in, mp_uint_t info_type) {
machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
size_t index = mp_machine_i2c_target_get_index(self);
machine_i2c_target_irq_obj_t *irq = MP_STATE_PORT(machine_i2c_target_irq_obj[index]);
if (info_type == MP_IRQ_INFO_FLAGS) {
return irq->flags;
} else if (info_type == MP_IRQ_INFO_TRIGGERS) {
return irq->trigger;
}
return 0;
}
static const mp_irq_methods_t machine_i2c_target_irq_methods = {
.trigger = machine_i2c_target_irq_trigger,
.info = machine_i2c_target_irq_info,
};
#if !MICROPY_PY_MACHINE_I2C_TARGET_FINALISER
void mp_machine_i2c_target_deinit_all(void) {
for (size_t i = 0; i < MICROPY_PY_MACHINE_I2C_TARGET_MAX; ++i) {
if (machine_i2c_target_data[i].state != STATE_INACTIVE) {
machine_i2c_target_deinit(MP_OBJ_FROM_PTR(&machine_i2c_target_obj[i]));
}
}
}
#endif
#endif // MICROPY_PY_MACHINE_I2C_TARGET

View File

@@ -30,20 +30,35 @@
#if MICROPY_PY_MACHINE_PULSE
MP_WEAK mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
mp_uint_t nchanges = 2;
mp_uint_t start = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) != pulse_level) {
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
return (mp_uint_t)-2;
for (;;) {
// Sample ticks and pin as close together as possible, and always in the same
// order each time around the loop. This gives the most accurate measurement.
mp_uint_t t = mp_hal_ticks_us();
int pin_value = mp_hal_pin_read(pin);
if (pin_value == pulse_level) {
// Pin is at desired value. Flip desired value and see if we are done.
pulse_level = 1 - pulse_level;
if (--nchanges == 0) {
return t - start;
}
start = t;
} else {
// Pin hasn't changed yet, check for timeout.
mp_uint_t dt = t - start;
if (dt >= timeout_us) {
return -nchanges;
}
// Allow a port to perform background task processing if needed.
#ifdef MICROPY_PY_MACHINE_TIME_PULSE_US_HOOK
MICROPY_PY_MACHINE_TIME_PULSE_US_HOOK(dt);
#endif
}
}
start = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) == pulse_level) {
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
return (mp_uint_t)-1;
}
}
return mp_hal_ticks_us() - start;
}
static mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {

View File

@@ -108,7 +108,7 @@ static mp_obj_t usb_device_submit_xfer(mp_obj_t self, mp_obj_t ep, mp_obj_t buff
//
// This C layer doesn't otherwise keep track of which endpoints the host
// is aware of (or not).
mp_raise_ValueError("ep");
mp_raise_ValueError(MP_ERROR_TEXT("ep"));
}
if (!usbd_edpt_claim(USBD_RHPORT, ep_addr)) {

View File

@@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
#define MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
#include "py/mpconfig.h"
// If you want to debug MBEDTLS uncomment the following and
// pass "3" to mbedtls_debug_set_threshold in socket_new.
// #define MBEDTLS_DEBUG_C
@@ -89,12 +91,18 @@
#define MBEDTLS_SHA384_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_PROTO_DTLS
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_USE_C
#if MICROPY_PY_SSL_DTLS
#define MBEDTLS_SSL_PROTO_DTLS
#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
#define MBEDTLS_SSL_COOKIE_C
#endif
// A port may enable this option to select additional bare-metal configuration.
#if MICROPY_MBEDTLS_CONFIG_BARE_METAL
@@ -115,4 +123,8 @@ void m_tracked_free(void *ptr);
#endif
// Workaround for a mimxrt platform driver header that defines ARRAY_SIZE,
// which is also defined in some mbedtls source files.
#undef ARRAY_SIZE
#endif // MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H

View File

@@ -290,12 +290,13 @@ static mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args,
static mp_obj_t bluetooth_ble_active(size_t n_args, const mp_obj_t *args) {
if (n_args == 2) {
// Boolean enable/disable argument supplied, set current state.
int err;
if (mp_obj_is_true(args[1])) {
int err = mp_bluetooth_init();
bluetooth_handle_errno(err);
err = mp_bluetooth_init();
} else {
mp_bluetooth_deinit();
err = mp_bluetooth_deinit();
}
bluetooth_handle_errno(err);
}
// Return current state.
return mp_obj_new_bool(mp_bluetooth_is_active());
@@ -340,7 +341,7 @@ static mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map
}
for (size_t i = 0; i < kwargs->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
if (mp_map_slot_is_filled(kwargs, i)) {
mp_map_elem_t *e = &kwargs->table[i];
switch (mp_obj_str_get_qstr(e->key)) {
case MP_QSTR_gap_name: {

View File

@@ -295,7 +295,7 @@ extern const mp_obj_type_t mp_type_bluetooth_uuid;
int mp_bluetooth_init(void);
// Disables the Bluetooth stack. Is a no-op when not enabled.
void mp_bluetooth_deinit(void);
int mp_bluetooth_deinit(void);
// Returns true when the Bluetooth stack is active.
bool mp_bluetooth_is_active(void);

View File

@@ -270,8 +270,7 @@ static void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, u
formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col);
}
static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
mp_arg_check_num(n_args, n_kw, 4, 5, false);
static mp_obj_t framebuf_make_new_helper(size_t n_args, const mp_obj_t *args_in, unsigned int buf_flags, mp_obj_framebuf_t *o) {
mp_int_t width = mp_obj_get_int(args_in[1]);
mp_int_t height = mp_obj_get_int(args_in[2]);
@@ -318,13 +317,15 @@ static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
mp_get_buffer_raise(args_in[0], &bufinfo, buf_flags);
if ((strides_required * stride + (height_required - strides_required) * width_required) * bpp / 8 > bufinfo.len) {
mp_raise_ValueError(NULL);
}
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type);
if (o == NULL) {
o = mp_obj_malloc(mp_obj_framebuf_t, (const mp_obj_type_t *)&mp_type_framebuf);
}
o->buf_obj = args_in[0];
o->buf = bufinfo.buf;
o->width = width;
@@ -335,6 +336,11 @@ static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
return MP_OBJ_FROM_PTR(o);
}
static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
mp_arg_check_num(n_args, n_kw, 4, 5, false);
return framebuf_make_new_helper(n_args, args_in, MP_BUFFER_WRITE, NULL);
}
static void framebuf_args(const mp_obj_t *args_in, mp_int_t *args_out, int n) {
for (int i = 0; i < n; ++i) {
args_out[i] = mp_obj_get_int(args_in[i + 1]);
@@ -707,13 +713,27 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_poly_obj, 5, 6, framebuf_pol
#endif // MICROPY_PY_ARRAY
static void get_readonly_framebuffer(mp_obj_t arg, mp_obj_framebuf_t *rofb) {
mp_obj_t fb = mp_obj_cast_to_native_base(arg, MP_OBJ_FROM_PTR(&mp_type_framebuf));
if (fb != MP_OBJ_NULL) {
*rofb = *(mp_obj_framebuf_t *)MP_OBJ_TO_PTR(fb);
} else {
// A tuple/list of the form: (buffer, width, height, format[, stride]).
size_t len;
mp_obj_t *items;
mp_obj_get_array(arg, &len, &items);
if (len < 4 || len > 5) {
mp_raise_ValueError(NULL);
}
framebuf_make_new_helper(len, items, MP_BUFFER_READ, rofb);
}
}
static mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) {
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
mp_obj_t source_in = mp_obj_cast_to_native_base(args_in[1], MP_OBJ_FROM_PTR(&mp_type_framebuf));
if (source_in == MP_OBJ_NULL) {
mp_raise_TypeError(NULL);
}
mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in);
mp_obj_framebuf_t source;
get_readonly_framebuffer(args_in[1], &source);
mp_int_t x = mp_obj_get_int(args_in[2]);
mp_int_t y = mp_obj_get_int(args_in[3]);
@@ -721,16 +741,17 @@ static mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) {
if (n_args > 4) {
key = mp_obj_get_int(args_in[4]);
}
mp_obj_framebuf_t *palette = NULL;
mp_obj_framebuf_t palette;
palette.buf = NULL;
if (n_args > 5 && args_in[5] != mp_const_none) {
palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args_in[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
get_readonly_framebuffer(args_in[5], &palette);
}
if (
(x >= self->width) ||
(y >= self->height) ||
(-x >= source->width) ||
(-y >= source->height)
(-x >= source.width) ||
(-y >= source.height)
) {
// Out of bounds, no-op.
return mp_const_none;
@@ -741,15 +762,15 @@ static mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) {
int y0 = MAX(0, y);
int x1 = MAX(0, -x);
int y1 = MAX(0, -y);
int x0end = MIN(self->width, x + source->width);
int y0end = MIN(self->height, y + source->height);
int x0end = MIN(self->width, x + source.width);
int y0end = MIN(self->height, y + source.height);
for (; y0 < y0end; ++y0) {
int cx1 = x1;
for (int cx0 = x0; cx0 < x0end; ++cx0) {
uint32_t col = getpixel(source, cx1, y1);
if (palette) {
col = getpixel(palette, col, 0);
uint32_t col = getpixel(&source, cx1, y1);
if (palette.buf) {
col = getpixel(&palette, col, 0);
}
if (col != (uint32_t)key) {
setpixel(self, cx0, y0, col);

View File

@@ -160,7 +160,8 @@ static mp_obj_t mod_json_load(mp_obj_t stream_obj) {
for (;;) {
cont:
if (S_END(s)) {
break;
// Input finished abruptly in the middle of a composite entity.
goto fail;
}
mp_obj_t next = MP_OBJ_NULL;
bool enter = false;

View File

@@ -70,6 +70,10 @@
#define TCP_NODELAY TF_NODELAY
// Socket flags
#define MSG_PEEK 0x01
#define MSG_DONTWAIT 0x02
// For compatibilily with older lwIP versions.
#ifndef ip_set_option
#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt))
@@ -286,6 +290,15 @@ static const int error_lookup_table[] = {
#define MOD_NETWORK_SOCK_DGRAM (2)
#define MOD_NETWORK_SOCK_RAW (3)
// Total queue length for buffered UDP/raw incoming packets.
#define LWIP_INCOMING_PACKET_QUEUE_LEN (4)
typedef struct _lwip_incoming_packet_t {
struct pbuf *pbuf;
ip_addr_t peer_addr;
uint16_t peer_port;
} lwip_incoming_packet_t;
typedef struct _lwip_socket_obj_t {
mp_obj_base_t base;
@@ -294,8 +307,11 @@ typedef struct _lwip_socket_obj_t {
struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb;
// Data structure that holds incoming pbuf's.
// Each socket type has different state that it needs to keep track of.
volatile union {
struct pbuf *pbuf;
// TCP listening sockets have a queue of incoming connections, implemented as a ringbuffer.
struct {
uint8_t alloc;
uint8_t iget;
@@ -305,10 +321,23 @@ typedef struct _lwip_socket_obj_t {
struct tcp_pcb **array; // if alloc != 0
} tcp;
} connection;
// Connected TCP sockets have a single incoming pbuf that new data is appended to.
struct {
struct pbuf *pbuf;
} tcp;
// UDP and raw sockets have a queue of incoming pbuf's, implemented as a ringbuffer.
struct {
uint8_t iget; // ringbuffer read index
uint8_t iput; // ringbuffer write index
lwip_incoming_packet_t *array;
} udp_raw;
} incoming;
mp_obj_t callback;
ip_addr_t peer;
mp_uint_t peer_port;
ip_addr_t tcp_peer_addr;
mp_uint_t tcp_peer_port;
mp_uint_t timeout;
uint16_t recv_offset;
@@ -347,9 +376,21 @@ static void lwip_socket_free_incoming(lwip_socket_obj_t *socket) {
&& socket->pcb.tcp->state == LISTEN;
if (!socket_is_listener) {
if (socket->incoming.pbuf != NULL) {
pbuf_free(socket->incoming.pbuf);
socket->incoming.pbuf = NULL;
if (socket->type == MOD_NETWORK_SOCK_STREAM) {
if (socket->incoming.tcp.pbuf != NULL) {
pbuf_free(socket->incoming.tcp.pbuf);
socket->incoming.tcp.pbuf = NULL;
}
} else {
for (size_t i = 0; i < LWIP_INCOMING_PACKET_QUEUE_LEN; ++i) {
lwip_incoming_packet_t *slot = &socket->incoming.udp_raw.array[i];
if (slot->pbuf != NULL) {
pbuf_free(slot->pbuf);
slot->pbuf = NULL;
}
}
socket->incoming.udp_raw.iget = 0;
socket->incoming.udp_raw.iput = 0;
}
} else {
uint8_t alloc = socket->incoming.connection.alloc;
@@ -407,6 +448,19 @@ static inline void exec_user_callback(lwip_socket_obj_t *socket) {
}
}
static void udp_raw_incoming(lwip_socket_obj_t *socket, struct pbuf *p, const ip_addr_t *addr, u16_t port) {
lwip_incoming_packet_t *slot = &socket->incoming.udp_raw.array[socket->incoming.udp_raw.iput];
if (slot->pbuf != NULL) {
// No room in the inn, drop the packet.
pbuf_free(p);
} else {
slot->pbuf = p;
slot->peer_addr = *addr;
slot->peer_port = port;
socket->incoming.udp_raw.iput = (socket->incoming.udp_raw.iput + 1) % LWIP_INCOMING_PACKET_QUEUE_LEN;
}
}
#if MICROPY_PY_LWIP_SOCK_RAW
// Callback for incoming raw packets.
#if LWIP_VERSION_MAJOR < 2
@@ -416,13 +470,7 @@ static u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, c
#endif
{
lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
if (socket->incoming.pbuf != NULL) {
pbuf_free(p);
} else {
socket->incoming.pbuf = p;
memcpy(&socket->peer, addr, sizeof(socket->peer));
}
udp_raw_incoming(socket, p, addr, 0);
return 1; // we ate the packet
}
#endif
@@ -436,15 +484,7 @@ static void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p,
#endif
{
lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
if (socket->incoming.pbuf != NULL) {
// That's why they call it "unreliable". No room in the inn, drop the packet.
pbuf_free(p);
} else {
socket->incoming.pbuf = p;
socket->peer_port = (mp_uint_t)port;
memcpy(&socket->peer, addr, sizeof(socket->peer));
}
udp_raw_incoming(socket, p, addr, port);
}
// Callback for general tcp errors.
@@ -562,13 +602,13 @@ static err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err
return ERR_OK;
}
if (socket->incoming.pbuf == NULL) {
socket->incoming.pbuf = p;
if (socket->incoming.tcp.pbuf == NULL) {
socket->incoming.tcp.pbuf = p;
} else {
#ifdef SOCKET_SINGLE_PBUF
return ERR_BUF;
#else
pbuf_cat(socket->incoming.pbuf, p);
pbuf_cat(socket->incoming.tcp.pbuf, p);
#endif
}
@@ -637,18 +677,20 @@ static mp_uint_t lwip_raw_udp_send(lwip_socket_obj_t *socket, const byte *buf, m
}
// Helper function for recv/recvfrom to handle raw/UDP packets
static mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, ip_addr_t *ip, mp_uint_t *port, int *_errno) {
static mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, mp_int_t flags, ip_addr_t *ip, mp_uint_t *port, int *_errno) {
if (socket->incoming.pbuf == NULL) {
if (socket->timeout == 0) {
// Non-blocking socket.
lwip_incoming_packet_t *slot = &socket->incoming.udp_raw.array[socket->incoming.udp_raw.iget];
if (slot->pbuf == NULL) {
// Non-blocking socket or flag
if (socket->timeout == 0 || (flags & MSG_DONTWAIT)) {
*_errno = MP_EAGAIN;
return -1;
}
// Wait for data to arrive on UDP socket.
mp_uint_t start = mp_hal_ticks_ms();
while (socket->incoming.pbuf == NULL) {
while (slot->pbuf == NULL) {
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
*_errno = MP_ETIMEDOUT;
return -1;
@@ -658,17 +700,20 @@ static mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_u
}
if (ip != NULL) {
memcpy(ip, &socket->peer, sizeof(socket->peer));
*port = socket->peer_port;
*ip = slot->peer_addr;
*port = slot->peer_port;
}
struct pbuf *p = socket->incoming.pbuf;
struct pbuf *p = slot->pbuf;
MICROPY_PY_LWIP_ENTER
u16_t result = pbuf_copy_partial(p, buf, ((p->tot_len > len) ? len : p->tot_len), 0);
pbuf_free(p);
socket->incoming.pbuf = NULL;
if ((flags & MSG_PEEK) == 0) {
pbuf_free(p);
slot->pbuf = NULL;
socket->incoming.udp_raw.iget = (socket->incoming.udp_raw.iget + 1) % LWIP_INCOMING_PACKET_QUEUE_LEN;
}
MICROPY_PY_LWIP_EXIT
@@ -776,14 +821,20 @@ static mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
}
// Helper function for recv/recvfrom to handle TCP packets
static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, mp_int_t flags, int *_errno) {
// Check for any pending errors
STREAM_ERROR_CHECK(socket);
if (socket->incoming.pbuf == NULL) {
if (socket->state == STATE_LISTENING) {
// original socket in listening state, not the accepted connection.
*_errno = MP_ENOTCONN;
return -1;
}
// Non-blocking socket
if (socket->timeout == 0) {
if (socket->incoming.tcp.pbuf == NULL) {
// Non-blocking socket or flag
if (socket->timeout == 0 || (flags & MSG_DONTWAIT)) {
if (socket->state == STATE_PEER_CLOSED) {
return 0;
}
@@ -792,7 +843,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
}
mp_uint_t start = mp_hal_ticks_ms();
while (socket->state == STATE_CONNECTED && socket->incoming.pbuf == NULL) {
while (socket->state == STATE_CONNECTED && socket->incoming.tcp.pbuf == NULL) {
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
*_errno = MP_ETIMEDOUT;
return -1;
@@ -801,7 +852,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
}
if (socket->state == STATE_PEER_CLOSED) {
if (socket->incoming.pbuf == NULL) {
if (socket->incoming.tcp.pbuf == NULL) {
// socket closed and no data left in buffer
return 0;
}
@@ -819,7 +870,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
assert(socket->pcb.tcp != NULL);
struct pbuf *p = socket->incoming.pbuf;
struct pbuf *p = socket->incoming.tcp.pbuf;
mp_uint_t remaining = p->len - socket->recv_offset;
if (len > remaining) {
@@ -828,19 +879,21 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
memcpy(buf, (byte *)p->payload + socket->recv_offset, len);
remaining -= len;
if (remaining == 0) {
socket->incoming.pbuf = p->next;
// If we don't ref here, free() will free the entire chain,
// if we ref, it does what we need: frees 1st buf, and decrements
// next buf's refcount back to 1.
pbuf_ref(p->next);
pbuf_free(p);
socket->recv_offset = 0;
} else {
socket->recv_offset += len;
if ((flags & MSG_PEEK) == 0) {
remaining -= len;
if (remaining == 0) {
socket->incoming.tcp.pbuf = p->next;
// If we don't ref here, free() will free the entire chain,
// if we ref, it does what we need: frees 1st buf, and decrements
// next buf's refcount back to 1.
pbuf_ref(p->next);
pbuf_free(p);
socket->recv_offset = 0;
} else {
socket->recv_offset += len;
}
tcp_recved(socket->pcb.tcp, len);
}
tcp_recved(socket->pcb.tcp, len);
MICROPY_PY_LWIP_EXIT
@@ -854,8 +907,18 @@ static const mp_obj_type_t lwip_socket_type;
static void lwip_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
lwip_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<socket state=%d timeout=%d incoming=%p off=%d>", self->state, self->timeout,
self->incoming.pbuf, self->recv_offset);
mp_printf(print, "<socket state=%d timeout=" UINT_FMT " incoming=", self->state, self->timeout);
if (self->type == MOD_NETWORK_SOCK_STREAM) {
mp_printf(print, "%p off=%d>", self->incoming.tcp.pbuf, self->recv_offset);
} else {
int num_in_queue = 0;
for (size_t i = 0; i < LWIP_INCOMING_PACKET_QUEUE_LEN; ++i) {
if (self->incoming.udp_raw.array[i].pbuf != NULL) {
++num_in_queue;
}
}
mp_printf(print, "%d>", num_in_queue);
}
}
// FIXME: Only supports two arguments at present
@@ -884,16 +947,22 @@ static mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s
socket->incoming.connection.tcp.item = NULL;
break;
case MOD_NETWORK_SOCK_DGRAM:
socket->pcb.udp = udp_new();
socket->incoming.pbuf = NULL;
break;
#if MICROPY_PY_LWIP_SOCK_RAW
case MOD_NETWORK_SOCK_RAW: {
mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int(args[2]);
socket->pcb.raw = raw_new(proto);
break;
}
case MOD_NETWORK_SOCK_RAW:
#endif
if (socket->type == MOD_NETWORK_SOCK_DGRAM) {
socket->pcb.udp = udp_new();
}
#if MICROPY_PY_LWIP_SOCK_RAW
else {
mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int(args[2]);
socket->pcb.raw = raw_new(proto);
}
#endif
socket->incoming.udp_raw.iget = 0;
socket->incoming.udp_raw.iput = 0;
socket->incoming.udp_raw.array = m_new0(lwip_incoming_packet_t, LWIP_INCOMING_PACKET_QUEUE_LEN);
break;
default:
mp_raise_OSError(MP_EINVAL);
}
@@ -1075,7 +1144,7 @@ static mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
// ...and set up the new socket for it.
socket2->domain = MOD_NETWORK_AF_INET;
socket2->type = MOD_NETWORK_SOCK_STREAM;
socket2->incoming.pbuf = NULL;
socket2->incoming.tcp.pbuf = NULL;
socket2->timeout = socket->timeout;
socket2->state = STATE_CONNECTED;
socket2->recv_offset = 0;
@@ -1130,8 +1199,8 @@ static mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
socket->state = STATE_NEW;
mp_raise_OSError(error_lookup_table[-err]);
}
socket->peer_port = (mp_uint_t)port;
memcpy(&socket->peer, &dest, sizeof(socket->peer));
socket->tcp_peer_addr = dest;
socket->tcp_peer_port = (mp_uint_t)port;
MICROPY_PY_LWIP_EXIT
// And now we wait...
@@ -1216,40 +1285,58 @@ static mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_send_obj, lwip_socket_send);
static mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
// Common implementation for recv & recvfrom
static mp_obj_t lwip_socket_recv_common(size_t n_args, const mp_obj_t *args, ip_addr_t *ip, mp_uint_t *port) {
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(args[0]);
mp_int_t len = mp_obj_get_int(args[1]);
mp_int_t flags = n_args > 2 ? mp_obj_get_int(args[2]) : 0;
int _errno;
vstr_t vstr;
mp_uint_t ret = 0;
lwip_socket_check_connected(socket);
mp_int_t len = mp_obj_get_int(len_in);
vstr_t vstr;
vstr_init_len(&vstr, len);
mp_uint_t ret = 0;
switch (socket->type) {
case MOD_NETWORK_SOCK_STREAM: {
ret = lwip_tcp_receive(socket, (byte *)vstr.buf, len, &_errno);
case MOD_NETWORK_SOCK_STREAM:
if (ip != NULL) {
*ip = socket->tcp_peer_addr;
*port = (mp_uint_t)socket->tcp_peer_port;
}
ret = lwip_tcp_receive(socket, (byte *)vstr.buf, len, flags, &_errno);
break;
}
case MOD_NETWORK_SOCK_DGRAM:
#if MICROPY_PY_LWIP_SOCK_RAW
case MOD_NETWORK_SOCK_RAW:
#endif
ret = lwip_raw_udp_receive(socket, (byte *)vstr.buf, len, NULL, NULL, &_errno);
ret = lwip_raw_udp_receive(socket, (byte *)vstr.buf, len, flags, ip, port, &_errno);
break;
}
if (ret == -1) {
mp_raise_OSError(_errno);
}
if (ret == 0) {
return mp_const_empty_bytes;
}
vstr.len = ret;
return mp_obj_new_bytes_from_vstr(&vstr);
}
static MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recv_obj, lwip_socket_recv);
static mp_obj_t lwip_socket_recv(size_t n_args, const mp_obj_t *args) {
return lwip_socket_recv_common(n_args, args, NULL, NULL);
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_socket_recv_obj, 2, 3, lwip_socket_recv);
static mp_obj_t lwip_socket_recvfrom(size_t n_args, const mp_obj_t *args) {
ip_addr_t ip;
mp_uint_t port;
mp_obj_t tuple[2];
tuple[0] = lwip_socket_recv_common(n_args, args, &ip, &port);
tuple[1] = lwip_format_inet_addr(&ip, port);
return mp_obj_new_tuple(2, tuple);
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_socket_recvfrom_obj, 2, 3, lwip_socket_recvfrom);
static mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
@@ -1284,50 +1371,6 @@ static mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t
}
static MP_DEFINE_CONST_FUN_OBJ_3(lwip_socket_sendto_obj, lwip_socket_sendto);
static mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
int _errno;
lwip_socket_check_connected(socket);
mp_int_t len = mp_obj_get_int(len_in);
vstr_t vstr;
vstr_init_len(&vstr, len);
ip_addr_t ip;
mp_uint_t port;
mp_uint_t ret = 0;
switch (socket->type) {
case MOD_NETWORK_SOCK_STREAM: {
memcpy(&ip, &socket->peer, sizeof(socket->peer));
port = (mp_uint_t)socket->peer_port;
ret = lwip_tcp_receive(socket, (byte *)vstr.buf, len, &_errno);
break;
}
case MOD_NETWORK_SOCK_DGRAM:
#if MICROPY_PY_LWIP_SOCK_RAW
case MOD_NETWORK_SOCK_RAW:
#endif
ret = lwip_raw_udp_receive(socket, (byte *)vstr.buf, len, &ip, &port, &_errno);
break;
}
if (ret == -1) {
mp_raise_OSError(_errno);
}
mp_obj_t tuple[2];
if (ret == 0) {
tuple[0] = mp_const_empty_bytes;
} else {
vstr.len = ret;
tuple[0] = mp_obj_new_bytes_from_vstr(&vstr);
}
tuple[1] = lwip_format_inet_addr(&ip, port);
return mp_obj_new_tuple(2, tuple);
}
static MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recvfrom_obj, lwip_socket_recvfrom);
static mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
lwip_socket_check_connected(socket);
@@ -1487,12 +1530,12 @@ static mp_uint_t lwip_socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, i
switch (socket->type) {
case MOD_NETWORK_SOCK_STREAM:
return lwip_tcp_receive(socket, buf, size, errcode);
return lwip_tcp_receive(socket, buf, size, 0, errcode);
case MOD_NETWORK_SOCK_DGRAM:
#if MICROPY_PY_LWIP_SOCK_RAW
case MOD_NETWORK_SOCK_RAW:
#endif
return lwip_raw_udp_receive(socket, buf, size, NULL, NULL, errcode);
return lwip_raw_udp_receive(socket, buf, size, 0, NULL, NULL, errcode);
}
// Unreachable
return MP_STREAM_ERROR;
@@ -1537,9 +1580,15 @@ static mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
if (lwip_socket_incoming_array(socket)[socket->incoming.connection.iget] != NULL) {
ret |= MP_STREAM_POLL_RD;
}
} else if (socket->type == MOD_NETWORK_SOCK_STREAM) {
// For TCP sockets there is just one slot for incoming data
if (socket->incoming.tcp.pbuf != NULL) {
ret |= MP_STREAM_POLL_RD;
}
} else {
// Otherwise there is just one slot for incoming data
if (socket->incoming.pbuf != NULL) {
// Otherwise for UDP/raw there is a queue of incoming data
lwip_incoming_packet_t *slot = &socket->incoming.udp_raw.array[socket->incoming.udp_raw.iget];
if (slot->pbuf != NULL) {
ret |= MP_STREAM_POLL_RD;
}
}
@@ -1858,6 +1907,8 @@ static const mp_rom_map_elem_t mp_module_lwip_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(IP_PROTO_TCP) },
{ MP_ROM_QSTR(MP_QSTR_TCP_NODELAY), MP_ROM_INT(TCP_NODELAY) },
{ MP_ROM_QSTR(MP_QSTR_MSG_PEEK), MP_ROM_INT(MSG_PEEK) },
{ MP_ROM_QSTR(MP_QSTR_MSG_DONTWAIT), MP_ROM_INT(MSG_DONTWAIT) },
};
static MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table);

View File

@@ -45,11 +45,11 @@
static void mp_machine_idle(void);
#if MICROPY_PY_MACHINE_BOOTLOADER
NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args);
MP_NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args);
#endif
#if MICROPY_PY_MACHINE_RESET
NORETURN static void mp_machine_reset(void);
MP_NORETURN static void mp_machine_reset(void);
static mp_int_t mp_machine_reset_cause(void);
#endif
@@ -58,7 +58,7 @@ static mp_obj_t mp_machine_unique_id(void);
static mp_obj_t mp_machine_get_freq(void);
static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args);
static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args);
NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args);
MP_NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args);
#endif
// The port can provide additional machine-module implementation in this file.
@@ -67,7 +67,7 @@ NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args);
#endif
#if MICROPY_PY_MACHINE_BOOTLOADER
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
MP_NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
mp_machine_bootloader(n_args, args);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
@@ -81,7 +81,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
#if MICROPY_PY_MACHINE_RESET
NORETURN static mp_obj_t machine_reset(void) {
MP_NORETURN static mp_obj_t machine_reset(void) {
mp_machine_reset();
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
@@ -116,7 +116,7 @@ static mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep);
NORETURN static mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) {
MP_NORETURN static mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) {
mp_machine_deepsleep(n_args, args);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep);
@@ -219,6 +219,9 @@ static const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_I2C
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_I2C_TARGET
{ MP_ROM_QSTR(MP_QSTR_I2CTarget), MP_ROM_PTR(&machine_i2c_target_type) },
#endif
#if MICROPY_PY_MACHINE_I2S
{ MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) },
#endif

View File

@@ -129,6 +129,7 @@
// A port must provide these types, but they are otherwise opaque.
typedef struct _machine_adc_obj_t machine_adc_obj_t;
typedef struct _machine_adc_block_obj_t machine_adc_block_obj_t;
typedef struct _machine_i2c_target_obj_t machine_i2c_target_obj_t;
typedef struct _machine_i2s_obj_t machine_i2s_obj_t;
typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
typedef struct _machine_uart_obj_t machine_uart_obj_t;
@@ -203,6 +204,7 @@ extern const machine_mem_obj_t machine_mem32_obj;
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_adc_block_type;
extern const mp_obj_type_t machine_i2c_type;
extern const mp_obj_type_t machine_i2c_target_type;
extern const mp_obj_type_t machine_i2s_type;
extern const mp_obj_type_t machine_mem_type;
extern const mp_obj_type_t machine_pin_type;
@@ -242,7 +244,7 @@ uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);
uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);
#endif
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
MP_NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len);
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
@@ -261,6 +263,10 @@ int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n
int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
#endif
#if MICROPY_PY_MACHINE_I2C_TARGET
void mp_machine_i2c_target_deinit_all(void);
#endif
#if MICROPY_PY_MACHINE_SPI
mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj);

View File

@@ -40,6 +40,19 @@
#if MICROPY_PY_NETWORK_CYW43
// So that CYW43_LINK_xxx constants are available to MICROPY_PORT_NETWORK_INTERFACES.
#include "lib/cyw43-driver/src/cyw43.h"
extern const struct _mp_obj_type_t mp_network_cyw43_type;
#endif
#if MICROPY_PY_NETWORK_WIZNET5K
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
#endif
#if MICROPY_PY_NETWORK_NINAW10
extern const struct _mp_obj_type_t mod_network_nic_type_nina;
#endif
#if MICROPY_PY_NETWORK_ESP_HOSTED
extern const struct _mp_obj_type_t mod_network_esp_hosted_type;
#endif
#ifdef MICROPY_PY_NETWORK_INCLUDEFILE
@@ -166,6 +179,32 @@ static const mp_rom_map_elem_t mp_module_network_globals_table[] = {
MICROPY_PORT_NETWORK_INTERFACES
#endif
#if MICROPY_PY_NETWORK_CYW43
{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) },
// CYW43 status constants, currently for rp2 port only.
// TODO move these to WIFI module for all ports.
#if defined(PICO_PROGRAM_NAME) && defined(CYW43_LINK_DOWN)
{ MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(CYW43_LINK_DOWN) },
{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(CYW43_LINK_JOIN) },
{ MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(CYW43_LINK_BADAUTH) },
{ MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(CYW43_LINK_NONET) },
{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(CYW43_LINK_FAIL) },
{ MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(CYW43_LINK_UP) },
#endif
#endif
#if MICROPY_PY_NETWORK_WIZNET5K
{ MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
#endif
#if MICROPY_PY_NETWORK_NINAW10
{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_nina) },
#endif
#if MICROPY_PY_NETWORK_ESP_HOSTED
{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_esp_hosted_type) },
#endif
// Allow a port to take mostly full control of the network module.
#ifdef MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE
#include MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE

View File

@@ -60,6 +60,11 @@ extern char mod_network_country_code[2];
#define MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN (32)
#endif
#if MICROPY_PY_NETWORK_NINAW10
// This Network interface requires the extended socket state.
#define MICROPY_PY_SOCKET_EXTENDED_STATE (1)
#endif
// This is a null-terminated string.
extern char mod_network_hostname_data[MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN + 1];
@@ -77,6 +82,9 @@ extern const struct _mp_obj_type_t mp_network_ppp_lwip_type;
#endif
struct netif;
void sys_untimeout_all_with_arg(void *arg);
void mod_network_lwip_init(void);
void mod_network_lwip_poll_wrapper(uint32_t ticks_ms);
mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args);

View File

@@ -427,6 +427,9 @@ static mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
const char *re_str = mp_obj_str_get_str(args[0]);
int size = re1_5_sizecode(re_str);
if (size == -1) {
#if MICROPY_ERROR_REPORTING >= MICROPY_ERROR_REPORTING_NORMAL
mp_raise_ValueError(MP_ERROR_TEXT("regex too complex"));
#endif
goto error;
}
mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, re.insts, char, size, (mp_obj_type_t *)&re_type);

View File

@@ -58,7 +58,7 @@ static mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
return mp_time_localtime_get();
} else {
// Convert given seconds to tuple.
mp_int_t seconds = mp_obj_get_int(args[0]);
mp_timestamp_t seconds = timeutils_obj_get_timestamp(args[0]);
timeutils_struct_time_t tm;
timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
@@ -90,7 +90,7 @@ static mp_obj_t time_mktime(mp_obj_t tuple) {
mp_raise_TypeError(MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9"));
}
return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
return timeutils_obj_from_timestamp(timeutils_mktime(mp_obj_get_int(elem[0]),
mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
}

View File

@@ -105,7 +105,7 @@ static const char *const ssl_error_tab2[] = {
"NOT_SUPPORTED",
};
static NORETURN void ssl_raise_error(int err) {
static MP_NORETURN void ssl_raise_error(int err) {
MP_STATIC_ASSERT(SSL_NOT_OK - 3 == SSL_EAGAIN);
MP_STATIC_ASSERT(SSL_ERROR_CONN_LOST - 18 == SSL_ERROR_NOT_SUPPORTED);

View File

@@ -62,6 +62,9 @@
#include "mbedtls/ecdsa.h"
#include "mbedtls/asn1.h"
#endif
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
#include "mbedtls/ssl_cookie.h"
#endif
#ifndef MICROPY_MBEDTLS_CONFIG_BARE_METAL
#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (0)
@@ -75,7 +78,7 @@
#define MP_PROTOCOL_TLS_CLIENT 0
#define MP_PROTOCOL_TLS_SERVER MP_ENDPOINT_IS_SERVER
#define MP_PROTOCOL_DTLS_CLIENT MP_TRANSPORT_IS_DTLS
#define MP_PROTOCOL_DTLS_SERVER MP_ENDPOINT_IS_SERVER | MP_TRANSPORT_IS_DTLS
#define MP_PROTOCOL_DTLS_SERVER (MP_ENDPOINT_IS_SERVER | MP_TRANSPORT_IS_DTLS)
// This corresponds to an SSLContext object.
typedef struct _mp_obj_ssl_context_t {
@@ -92,6 +95,10 @@ typedef struct _mp_obj_ssl_context_t {
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
mp_obj_t ecdsa_sign_callback;
#endif
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
bool is_dtls_server;
mbedtls_ssl_cookie_ctx cookie_ctx;
#endif
} mp_obj_ssl_context_t;
// This corresponds to an SSLSocket object.
@@ -117,7 +124,8 @@ static const mp_obj_type_t ssl_socket_type;
static const MP_DEFINE_STR_OBJ(mbedtls_version_obj, MBEDTLS_VERSION_STRING_FULL);
static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname);
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname,
mp_obj_t client_id);
/******************************************************************************/
// Helper functions.
@@ -147,7 +155,7 @@ static const unsigned char *asn1_get_data(mp_obj_t obj, size_t *out_len) {
return (const unsigned char *)str;
}
static NORETURN void mbedtls_raise_error(int err) {
static MP_NORETURN void mbedtls_raise_error(int err) {
// Handle special cases.
if (err == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
mp_raise_OSError(MP_ENOMEM);
@@ -320,6 +328,19 @@ static mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
mbedtls_ssl_conf_dbg(&self->conf, mbedtls_debug, NULL);
#endif
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
self->is_dtls_server = (protocol == MP_PROTOCOL_DTLS_SERVER);
if (self->is_dtls_server) {
mbedtls_ssl_cookie_init(&self->cookie_ctx);
ret = mbedtls_ssl_cookie_setup(&self->cookie_ctx, mbedtls_ctr_drbg_random, &self->ctr_drbg);
if (ret != 0) {
mbedtls_raise_error(ret);
}
mbedtls_ssl_conf_dtls_cookies(&self->conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
&self->cookie_ctx);
}
#endif // MBEDTLS_SSL_DTLS_HELLO_VERIFY
return MP_OBJ_FROM_PTR(self);
}
@@ -366,6 +387,11 @@ static mp_obj_t ssl_context___del__(mp_obj_t self_in) {
mbedtls_ctr_drbg_free(&self->ctr_drbg);
mbedtls_entropy_free(&self->entropy);
mbedtls_ssl_config_free(&self->conf);
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
if (self->is_dtls_server) {
mbedtls_ssl_cookie_free(&self->cookie_ctx);
}
#endif
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(ssl_context___del___obj, ssl_context___del__);
@@ -468,11 +494,14 @@ static mp_obj_t ssl_context_load_verify_locations(mp_obj_t self_in, mp_obj_t cad
static MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_load_verify_locations_obj, ssl_context_load_verify_locations);
static mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname };
enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname, ARG_client_id };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_do_handshake_on_connect, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
{ MP_QSTR_client_id, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
#endif
};
// Parse arguments.
@@ -481,9 +510,14 @@ static mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args,
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_obj_t client_id = mp_const_none;
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
client_id = args[ARG_client_id].u_obj;
#endif
// Create and return the new SSLSocket object.
return ssl_socket_make_new(self, sock, args[ARG_server_side].u_bool,
args[ARG_do_handshake_on_connect].u_bool, args[ARG_server_hostname].u_obj);
args[ARG_do_handshake_on_connect].u_bool, args[ARG_server_hostname].u_obj, client_id);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_context_wrap_socket_obj, 2, ssl_context_wrap_socket);
@@ -580,7 +614,7 @@ static int _mbedtls_timing_get_delay(void *ctx) {
#endif
static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname) {
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname, mp_obj_t client_id) {
// Store the current SSL context.
store_active_context(ssl_context);
@@ -605,7 +639,7 @@ static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
ret = mbedtls_ssl_setup(&o->ssl, &ssl_context->conf);
#if !MICROPY_MBEDTLS_CONFIG_BARE_METAL
if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
if (ret != 0) {
// If mbedTLS relies on platform libc heap for buffers (i.e. esp32
// port), then run a GC pass and then try again. This is useful because
// it may free a Python object (like an old SSL socket) whose finaliser
@@ -635,6 +669,20 @@ static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
mbedtls_ssl_set_timer_cb(&o->ssl, o, _mbedtls_timing_set_delay, _mbedtls_timing_get_delay);
#endif
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
if (ssl_context->is_dtls_server) {
// require the client_id parameter for DTLS (as per mbedTLS requirement)
ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
mp_buffer_info_t buf;
if (mp_get_buffer(client_id, &buf, MP_BUFFER_READ)) {
ret = mbedtls_ssl_set_client_transport_id(&o->ssl, buf.buf, buf.len);
}
if (ret != 0) {
goto cleanup;
}
}
#endif
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
if (do_handshake_on_connect) {

View File

@@ -89,7 +89,7 @@ typedef struct _mp_obj_uctypes_struct_t {
uint32_t flags;
} mp_obj_uctypes_struct_t;
static NORETURN void syntax_error(void) {
static MP_NORETURN void syntax_error(void) {
mp_raise_TypeError(MP_ERROR_TEXT("syntax error in uctypes descriptor"));
}
@@ -277,15 +277,18 @@ static mp_obj_t uctypes_struct_sizeof(size_t n_args, const mp_obj_t *args) {
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, uctypes_struct_sizeof);
static const char type2char[16] = {
'B', 'b', 'H', 'h', 'I', 'i', 'Q', 'q',
'-', '-', '-', '-', '-', '-', 'f', 'd'
};
static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) {
char struct_type = big_endian ? '>' : '<';
static const char type2char[16] = "BbHhIiQq------fd";
return mp_binary_get_val(struct_type, type2char[val_type], p, &p);
}
static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) {
char struct_type = big_endian ? '>' : '<';
static const char type2char[16] = "BbHhIiQq------fd";
mp_binary_set_val(struct_type, type2char[val_type], val, p, &p);
}

View File

@@ -27,6 +27,10 @@
#ifndef MICROPY_INCLUDED_EXTMOD_MPBTHCI_H
#define MICROPY_INCLUDED_EXTMOD_MPBTHCI_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#define MICROPY_PY_BLUETOOTH_HCI_READ_MODE_BYTE (0)
#define MICROPY_PY_BLUETOOTH_HCI_READ_MODE_PACKET (1)

View File

@@ -143,6 +143,9 @@ static mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) {
return mp_obj_new_bool(if_active[self->itf]);
} else {
bool value = mp_obj_is_true(args[1]);
if (!value && self->itf == CYW43_ITF_STA) {
cyw43_wifi_leave(self->cyw, self->itf);
}
cyw43_wifi_set_up(self->cyw, self->itf, value, get_country_code());
if_active[self->itf] = value;
return mp_const_none;

View File

@@ -48,6 +48,8 @@
#include "esp_hosted_wifi.h"
#include "esp_hosted_hal.h"
extern const mp_obj_type_t mod_network_esp_hosted_type;
typedef struct _esp_hosted_obj_t {
mp_obj_base_t base;
uint32_t itf;

View File

@@ -52,6 +52,19 @@ int mp_mod_network_prefer_dns_use_ip_version = 4;
// Implementations of network methods that can be used by any interface.
// This follows sys_untimeout but removes all timeouts with the given argument.
void sys_untimeout_all_with_arg(void *arg) {
for (struct sys_timeo **t = sys_timeouts_get_next_timeout(); *t != NULL;) {
if ((*t)->arg == arg) {
struct sys_timeo *next = (*t)->next;
memp_free(MEMP_SYS_TIMEOUT, *t);
*t = next;
} else {
t = &(*t)->next;
}
}
}
// This function provides the implementation of nic.ifconfig, is deprecated and will be removed.
// Use network.ipconfig and nic.ipconfig instead.
mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args) {

View File

@@ -24,6 +24,10 @@
* THE SOFTWARE.
*/
// This file is intended to closely match ports/esp32/network_ppp.c. Changes can
// and should probably be applied to both files. Compare them directly by using:
// git diff --no-index extmod/network_ppp_lwip.c ports/esp32/network_ppp.c
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/stream.h"
@@ -80,7 +84,6 @@ static void network_ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
break;
case PPPERR_USER:
if (self->state >= STATE_ERROR) {
network_ppp_stream_uart_irq_disable(self);
// Indicate that we are no longer connected and thus
// only need to free the PPP PCB, not close it.
self->state = STATE_ACTIVE;
@@ -121,6 +124,7 @@ static mp_obj_t network_ppp___del__(mp_obj_t self_in) {
self->state = STATE_INACTIVE;
ppp_close(self->pcb, 1);
}
network_ppp_stream_uart_irq_disable(self);
// Free PPP PCB and reset state.
self->state = STATE_INACTIVE;
ppp_free(self->pcb);
@@ -295,7 +299,8 @@ static mp_obj_t network_ppp_connect(size_t n_args, const mp_obj_t *args, mp_map_
ppp_set_auth(self->pcb, parsed_args[ARG_security].u_int, user_str, key_str);
}
netif_set_default(self->pcb->netif);
ppp_set_default(self->pcb);
ppp_set_usepeerdns(self->pcb, true);
if (ppp_connect(self->pcb, 0) != ERR_OK) {

View File

@@ -78,6 +78,8 @@
#endif
extern const mp_obj_type_t mod_network_nic_type_wiznet5k;
#ifndef printf
#define printf(...) mp_printf(MP_PYTHON_PRINTER, __VA_ARGS__)
#endif

View File

@@ -60,6 +60,7 @@
static uint8_t nimble_address_mode = BLE_OWN_ADDR_RANDOM;
#define NIMBLE_STARTUP_TIMEOUT 2000
#define NIMBLE_SHUTDOWN_TIMEOUT 500
// Any BLE_HS_xxx code not in this table will default to MP_EIO.
static int8_t ble_hs_err_to_errno_table[] = {
@@ -554,7 +555,7 @@ static void ble_hs_shutdown_stop_cb(int status, void *arg) {
static struct ble_hs_stop_listener ble_hs_shutdown_stop_listener;
void mp_bluetooth_nimble_port_shutdown(void) {
int mp_bluetooth_nimble_port_shutdown(void) {
DEBUG_printf("mp_bluetooth_nimble_port_shutdown (nimble default)\n");
// By default, just call ble_hs_stop directly and wait for the stack to stop.
@@ -562,9 +563,17 @@ void mp_bluetooth_nimble_port_shutdown(void) {
ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, NULL);
mp_uint_t timeout_start_ticks_ms = mp_hal_ticks_ms();
while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
mp_event_wait_indefinite();
mp_uint_t elapsed = mp_hal_ticks_ms() - timeout_start_ticks_ms;
if (elapsed > NIMBLE_SHUTDOWN_TIMEOUT) {
// Stack had not responded (via ble_hs_shutdown_stop_cb)
return MP_ETIMEDOUT;
}
mp_event_wait_ms(NIMBLE_SHUTDOWN_TIMEOUT - elapsed);
}
return 0;
}
#endif // !MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY
@@ -659,10 +668,11 @@ int mp_bluetooth_init(void) {
return 0;
}
void mp_bluetooth_deinit(void) {
int mp_bluetooth_deinit(void) {
DEBUG_printf("mp_bluetooth_deinit %d\n", mp_bluetooth_nimble_ble_state);
int ret = 0;
if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
return;
return 0;
}
// Must call ble_hs_stop() in a port-specific way to stop the background
@@ -675,7 +685,7 @@ void mp_bluetooth_deinit(void) {
DEBUG_printf("mp_bluetooth_deinit: starting port shutdown\n");
mp_bluetooth_nimble_port_shutdown();
ret = mp_bluetooth_nimble_port_shutdown();
assert(mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF);
} else {
mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF;
@@ -692,6 +702,7 @@ void mp_bluetooth_deinit(void) {
#endif
DEBUG_printf("mp_bluetooth_deinit: shut down\n");
return ret;
}
bool mp_bluetooth_is_active(void) {

View File

@@ -84,7 +84,7 @@ void mp_bluetooth_nimble_port_hci_deinit(void);
void mp_bluetooth_nimble_port_start(void);
// Tell the port to stop its background task.
void mp_bluetooth_nimble_port_shutdown(void);
int mp_bluetooth_nimble_port_shutdown(void);
// --- Called by the HCI UART layer to let us know when packets have been sent.
void mp_bluetooth_nimble_sent_hci_packet(void);

View File

@@ -326,7 +326,7 @@ static mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
} else {
mode |= MP_S_IFREG;
}
mp_int_t seconds = timeutils_seconds_since_epoch(
mp_timestamp_t seconds = timeutils_seconds_since_epoch(
1980 + ((fno.fdate >> 9) & 0x7f),
(fno.fdate >> 5) & 0x0f,
fno.fdate & 0x1f,
@@ -341,9 +341,9 @@ static mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
t->items[6] = mp_obj_new_int_from_uint(fno.fsize); // st_size
t->items[7] = mp_obj_new_int_from_uint(seconds); // st_atime
t->items[8] = mp_obj_new_int_from_uint(seconds); // st_mtime
t->items[9] = mp_obj_new_int_from_uint(seconds); // st_ctime
t->items[7] = timeutils_obj_from_timestamp(seconds); // st_atime
t->items[8] = timeutils_obj_from_timestamp(seconds); // st_mtime
t->items[9] = timeutils_obj_from_timestamp(seconds); // st_ctime
return MP_OBJ_FROM_PTR(t);
}

View File

@@ -104,6 +104,12 @@ static void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size
config->read_buffer = m_new(uint8_t, config->cache_size);
config->prog_buffer = m_new(uint8_t, config->cache_size);
config->lookahead_buffer = m_new(uint8_t, config->lookahead_size);
#ifdef LFS2_MULTIVERSION
// This can be set to override the on-disk lfs version.
// eg. for compat with lfs2 < v2.6 add the following to make:
// CFLAGS += '-DLFS2_MULTIVERSION=0x00020000'
config->disk_version = LFS2_MULTIVERSION;
#endif
#endif
}
@@ -300,7 +306,7 @@ static mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) {
struct LFSx_API (info) info;
int ret = LFSx_API(stat)(&self->lfs, path, &info);
if (ret < 0 || info.type != LFSx_MACRO(_TYPE_DIR)) {
mp_raise_OSError(-MP_ENOENT);
mp_raise_OSError(MP_ENOENT);
}
}
@@ -378,7 +384,7 @@ static mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) {
mp_raise_OSError(-ret);
}
mp_uint_t mtime = 0;
mp_timestamp_t mtime = 0;
#if LFS_BUILD_VERSION == 2
uint8_t mtime_buf[8];
lfs2_ssize_t sz = lfs2_getattr(&self->lfs, path, LFS_ATTR_MTIME, &mtime_buf, sizeof(mtime_buf));
@@ -400,9 +406,9 @@ static mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) {
t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
t->items[6] = mp_obj_new_int_from_uint(info.size); // st_size
t->items[7] = mp_obj_new_int_from_uint(mtime); // st_atime
t->items[8] = mp_obj_new_int_from_uint(mtime); // st_mtime
t->items[9] = mp_obj_new_int_from_uint(mtime); // st_ctime
t->items[7] = timeutils_obj_from_timestamp(mtime); // st_atime
t->items[8] = timeutils_obj_from_timestamp(mtime); // st_mtime
t->items[9] = timeutils_obj_from_timestamp(mtime); // st_ctime
return MP_OBJ_FROM_PTR(t);
}

View File

@@ -137,7 +137,7 @@ static mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, siz
vstr_add_char(&vfs->root, '/');
}
vfs->root_len = vfs->root.len;
vfs->readonly = false;
vfs->readonly = !MICROPY_VFS_POSIX_WRITABLE;
return MP_OBJ_FROM_PTR(vfs);
}
@@ -160,10 +160,21 @@ static mp_obj_t vfs_posix_umount(mp_obj_t self_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_umount_obj, vfs_posix_umount);
static inline bool vfs_posix_is_readonly(mp_obj_vfs_posix_t *self) {
return !MICROPY_VFS_POSIX_WRITABLE || self->readonly;
}
static void vfs_posix_require_writable(mp_obj_t self_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
if (vfs_posix_is_readonly(self)) {
mp_raise_OSError(MP_EROFS);
}
}
static mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
const char *mode = mp_obj_str_get_str(mode_in);
if (self->readonly
if (vfs_posix_is_readonly(self)
&& (strchr(mode, 'w') != NULL || strchr(mode, 'a') != NULL || strchr(mode, '+') != NULL)) {
mp_raise_OSError(MP_EROFS);
}
@@ -303,6 +314,7 @@ typedef struct _mp_obj_listdir_t {
} mp_obj_listdir_t;
static mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) {
vfs_posix_require_writable(self_in);
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
const char *path = vfs_posix_get_path_str(self, path_in);
MP_THREAD_GIL_EXIT();
@@ -320,11 +332,13 @@ static mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) {
static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_mkdir_obj, vfs_posix_mkdir);
static mp_obj_t vfs_posix_remove(mp_obj_t self_in, mp_obj_t path_in) {
vfs_posix_require_writable(self_in);
return vfs_posix_fun1_helper(self_in, path_in, unlink);
}
static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_remove_obj, vfs_posix_remove);
static mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_t new_path_in) {
vfs_posix_require_writable(self_in);
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
const char *old_path = vfs_posix_get_path_str(self, old_path_in);
const char *new_path = vfs_posix_get_path_str(self, new_path_in);
@@ -339,6 +353,7 @@ static mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_
static MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_rename_obj, vfs_posix_rename);
static mp_obj_t vfs_posix_rmdir(mp_obj_t self_in, mp_obj_t path_in) {
vfs_posix_require_writable(self_in);
return vfs_posix_fun1_helper(self_in, path_in, rmdir);
}
static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_rmdir_obj, vfs_posix_rmdir);

View File

@@ -2,7 +2,7 @@
#include <math.h>
#include <stdint.h>
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 || FLT_EVAL_METHOD==16
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON

View File

@@ -2141,7 +2141,7 @@ int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *cfg) {
.d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4,
.d.nlen = sizeof(superblock.d.magic),
.d.version = LFS1_DISK_VERSION,
.d.magic = {"littlefs"},
.d.magic = {'l', 'i', 't', 't', 'l', 'e', 'f', 's'},
.d.block_size = lfs1->cfg->block_size,
.d.block_count = lfs1->cfg->block_count,
.d.root = {lfs1->root[0], lfs1->root[1]},

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@ extern "C"
// Software library version
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
#define LFS2_VERSION 0x00020008
#define LFS2_VERSION 0x0002000b
#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16))
#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0))
@@ -52,16 +52,15 @@ typedef uint32_t lfs2_block_t;
#endif
// Maximum size of a file in bytes, may be redefined to limit to support other
// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the
// functions lfs2_file_seek, lfs2_file_size, and lfs2_file_tell will return
// incorrect values due to using signed integers. Stored in superblock and
// must be respected by other littlefs drivers.
// drivers. Limited on disk to <= 2147483647. Stored in superblock and must be
// respected by other littlefs drivers.
#ifndef LFS2_FILE_MAX
#define LFS2_FILE_MAX 2147483647
#endif
// Maximum size of custom attributes in bytes, may be redefined, but there is
// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022.
// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022. Stored
// in superblock and must be respected by other littlefs drivers.
#ifndef LFS2_ATTR_MAX
#define LFS2_ATTR_MAX 1022
#endif
@@ -205,7 +204,8 @@ struct lfs2_config {
// program sizes.
lfs2_size_t block_size;
// Number of erasable blocks on the device.
// Number of erasable blocks on the device. Defaults to block_count stored
// on disk when zero.
lfs2_size_t block_count;
// Number of erase cycles before littlefs evicts metadata logs and moves
@@ -226,9 +226,20 @@ struct lfs2_config {
// Size of the lookahead buffer in bytes. A larger lookahead buffer
// increases the number of blocks found during an allocation pass. The
// lookahead buffer is stored as a compact bitmap, so each byte of RAM
// can track 8 blocks. Must be a multiple of 8.
// can track 8 blocks.
lfs2_size_t lookahead_size;
// Threshold for metadata compaction during lfs2_fs_gc in bytes. Metadata
// pairs that exceed this threshold will be compacted during lfs2_fs_gc.
// Defaults to ~88% block_size when zero, though the default may change
// in the future.
//
// Note this only affects lfs2_fs_gc. Normal compactions still only occur
// when full.
//
// Set to -1 to disable metadata compaction during lfs2_fs_gc.
lfs2_size_t compact_thresh;
// Optional statically allocated read buffer. Must be cache_size.
// By default lfs2_malloc is used to allocate this buffer.
void *read_buffer;
@@ -237,25 +248,24 @@ struct lfs2_config {
// By default lfs2_malloc is used to allocate this buffer.
void *prog_buffer;
// Optional statically allocated lookahead buffer. Must be lookahead_size
// and aligned to a 32-bit boundary. By default lfs2_malloc is used to
// allocate this buffer.
// Optional statically allocated lookahead buffer. Must be lookahead_size.
// By default lfs2_malloc is used to allocate this buffer.
void *lookahead_buffer;
// Optional upper limit on length of file names in bytes. No downside for
// larger names except the size of the info struct which is controlled by
// the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX when zero. Stored in
// superblock and must be respected by other littlefs drivers.
// the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX or name_max stored on
// disk when zero.
lfs2_size_t name_max;
// Optional upper limit on files in bytes. No downside for larger files
// but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX when zero. Stored
// in superblock and must be respected by other littlefs drivers.
// but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX or file_max stored
// on disk when zero.
lfs2_size_t file_max;
// Optional upper limit on custom attributes in bytes. No downside for
// larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to
// LFS2_ATTR_MAX when zero.
// LFS2_ATTR_MAX or attr_max stored on disk when zero.
lfs2_size_t attr_max;
// Optional upper limit on total space given to metadata pairs in bytes. On
@@ -264,6 +274,15 @@ struct lfs2_config {
// Defaults to block_size when zero.
lfs2_size_t metadata_max;
// Optional upper limit on inlined files in bytes. Inlined files live in
// metadata and decrease storage requirements, but may be limited to
// improve metadata-related performance. Must be <= cache_size, <=
// attr_max, and <= block_size/8. Defaults to the largest possible
// inline_max when zero.
//
// Set to -1 to disable inlined files.
lfs2_size_t inline_max;
#ifdef LFS2_MULTIVERSION
// On-disk version to use when writing in the form of 16-bit major version
// + 16-bit minor version. This limiting metadata to what is supported by
@@ -430,19 +449,20 @@ typedef struct lfs2 {
lfs2_gstate_t gdisk;
lfs2_gstate_t gdelta;
struct lfs2_free {
lfs2_block_t off;
struct lfs2_lookahead {
lfs2_block_t start;
lfs2_block_t size;
lfs2_block_t i;
lfs2_block_t ack;
uint32_t *buffer;
} free;
lfs2_block_t next;
lfs2_block_t ckpoint;
uint8_t *buffer;
} lookahead;
const struct lfs2_config *cfg;
lfs2_size_t block_count;
lfs2_size_t name_max;
lfs2_size_t file_max;
lfs2_size_t attr_max;
lfs2_size_t inline_max;
#ifdef LFS2_MIGRATE
struct lfs21 *lfs21;
@@ -712,18 +732,6 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2);
// Returns a negative error code on failure.
int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data);
// Attempt to proactively find free blocks
//
// Calling this function is not required, but may allowing the offloading of
// the expensive block allocation scan to a less time-critical code path.
//
// Note: littlefs currently does not persist any found free blocks to disk.
// This may change in the future.
//
// Returns a negative error code on failure. Finding no free blocks is
// not an error.
int lfs2_fs_gc(lfs2_t *lfs2);
#ifndef LFS2_READONLY
// Attempt to make the filesystem consistent and ready for writing
//
@@ -736,11 +744,33 @@ int lfs2_fs_gc(lfs2_t *lfs2);
int lfs2_fs_mkconsistent(lfs2_t *lfs2);
#endif
#ifndef LFS2_READONLY
// Attempt any janitorial work
//
// This currently:
// 1. Calls mkconsistent if not already consistent
// 2. Compacts metadata > compact_thresh
// 3. Populates the block allocator
//
// Though additional janitorial work may be added in the future.
//
// Calling this function is not required, but may allow the offloading of
// expensive janitorial work to a less time-critical code path.
//
// Returns a negative error code on failure. Accomplishing nothing is not
// an error.
int lfs2_fs_gc(lfs2_t *lfs2);
#endif
#ifndef LFS2_READONLY
// Grows the filesystem to a new size, updating the superblock with the new
// block count.
//
// Note: This is irreversible.
// If LFS2_SHRINKNONRELOCATING is defined, this function will also accept
// block_counts smaller than the current configuration, after checking
// that none of the blocks that are being removed are in use.
// Note that littlefs's pseudorandom block allocation means that
// this is very unlikely to work in the general case.
//
// Returns a negative error code on failure.
int lfs2_fs_grow(lfs2_t *lfs2, lfs2_size_t block_count);

View File

@@ -11,6 +11,8 @@
#ifndef LFS2_CONFIG
// If user provides their own CRC impl we don't need this
#ifndef LFS2_CRC
// Software CRC implementation with small lookup table
uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) {
static const uint32_t rtable[16] = {
@@ -29,6 +31,7 @@ uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) {
return crc;
}
#endif
#endif

View File

@@ -8,6 +8,9 @@
#ifndef LFS2_UTIL_H
#define LFS2_UTIL_H
#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x)
#define LFS2_STRINGIZE2(x) #x
// Users can override lfs2_util.h with their own configuration by defining
// LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h).
//
@@ -15,11 +18,26 @@
// provided by the config file. To start, I would suggest copying lfs2_util.h
// and modifying as needed.
#ifdef LFS2_CONFIG
#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x)
#define LFS2_STRINGIZE2(x) #x
#include LFS2_STRINGIZE(LFS2_CONFIG)
#else
// Alternatively, users can provide a header file which defines
// macros and other things consumed by littlefs.
//
// For example, provide my_defines.h, which contains
// something like:
//
// #include <stddef.h>
// extern void *my_malloc(size_t sz);
// #define LFS2_MALLOC(sz) my_malloc(sz)
//
// And build littlefs with the header by defining LFS2_DEFINES.
// (-DLFS2_DEFINES=my_defines.h)
#ifdef LFS2_DEFINES
#include LFS2_STRINGIZE(LFS2_DEFINES)
#endif
// System includes
#include <stdint.h>
#include <stdbool.h>
@@ -177,10 +195,10 @@ static inline uint32_t lfs2_fromle32(uint32_t a) {
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
return __builtin_bswap32(a);
#else
return (((uint8_t*)&a)[0] << 0) |
(((uint8_t*)&a)[1] << 8) |
(((uint8_t*)&a)[2] << 16) |
(((uint8_t*)&a)[3] << 24);
return ((uint32_t)((uint8_t*)&a)[0] << 0) |
((uint32_t)((uint8_t*)&a)[1] << 8) |
((uint32_t)((uint8_t*)&a)[2] << 16) |
((uint32_t)((uint8_t*)&a)[3] << 24);
#endif
}
@@ -200,10 +218,10 @@ static inline uint32_t lfs2_frombe32(uint32_t a) {
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
return a;
#else
return (((uint8_t*)&a)[0] << 24) |
(((uint8_t*)&a)[1] << 16) |
(((uint8_t*)&a)[2] << 8) |
(((uint8_t*)&a)[3] << 0);
return ((uint32_t)((uint8_t*)&a)[0] << 24) |
((uint32_t)((uint8_t*)&a)[1] << 16) |
((uint32_t)((uint8_t*)&a)[2] << 8) |
((uint32_t)((uint8_t*)&a)[3] << 0);
#endif
}
@@ -212,12 +230,22 @@ static inline uint32_t lfs2_tobe32(uint32_t a) {
}
// Calculate CRC-32 with polynomial = 0x04c11db7
#ifdef LFS2_CRC
static inline uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) {
return LFS2_CRC(crc, buffer, size);
}
#else
uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size);
#endif
// Allocate memory, only used if buffers are not provided to littlefs
// Note, memory must be 64-bit aligned
//
// littlefs current has no alignment requirements, as it only allocates
// byte-level buffers.
static inline void *lfs2_malloc(size_t size) {
#ifndef LFS2_NO_MALLOC
#if defined(LFS2_MALLOC)
return LFS2_MALLOC(size);
#elif !defined(LFS2_NO_MALLOC)
return malloc(size);
#else
(void)size;
@@ -227,7 +255,9 @@ static inline void *lfs2_malloc(size_t size) {
// Deallocate memory, only used if buffers are not provided to littlefs
static inline void lfs2_free(void *p) {
#ifndef LFS2_NO_MALLOC
#if defined(LFS2_FREE)
LFS2_FREE(p);
#elif !defined(LFS2_NO_MALLOC)
free(p);
#else
(void)p;

Some files were not shown because too many files have changed in this diff Show More