508 Commits

Author SHA1 Message Date
e4422b860e rp2: Fix stacks for multicore operation
Unfortunately, no way to override this from board config.
2025-03-23 19:11:24 +01:00
0f26771a44 rp2: Modify linker script to run MP3 decoder from RAM 2025-03-04 22:57:09 +01:00
Mike Bell
29275e2c58 rp2/rp2_flash: Workaround multicore lockout not being reset.
With regression test.

See upstream bug https://github.com/raspberrypi/pico-sdk/issues/2201

Tested-by: Angus Gratton <angus@redyak.com.au>
Signed-off-by: Mike Bell <mdb036@gmail.com>
2025-03-04 20:12:18 +01:00
Damien George
732c2989c5 lib/pico-sdk: Update to version 2.1.1.
Release notes: https://github.com/raspberrypi/pico-sdk/releases/tag/2.1.1

Signed-off-by: Damien George <damien@micropython.org>
2025-03-04 19:49:20 +01:00
Peter Harper
ef5c3c043c rp2/mphalport: Add mp_hal_is_pin_reserved() function.
As cyw43 pins might be dynamic, add a function that returns if a pin is
reserved.  This is used by `MICROPY_HW_PIN_RESERVED` to prevent the pin IRQ
from being reset across a soft-reset.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2025-03-04 19:41:59 +01:00
Peter Harper
ba21be5215 rp2/cyw43_configport: Define cyw43 pins.
The cyw43 pins used to be hardcoded and `CYW43_PIN_WL_HOST_WAKE` and
`CYW43_PIN_WL_REG_ON` were in the `pico_w.h` board header.

This has been changed so the board header just defines the "default
version of the pins, e.g. `CYW43_DEFAULT_PIN_WL_HOST_WAKE`,
`CYW43_DEFAULT_PIN_WL_REG_ON` etc.

Set the pin values in `cyw43_configport.`h so `cyw43-driver` sees them and
allow them to be changed at runtime (dynamic) if required.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2025-03-04 19:40:17 +01:00
Phil Howard
8ba7af3a70 rp2/CMakeLists.txt: Add components required by bootrom.h.
Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2025-03-04 19:38:19 +01:00
Peter Harper
08513e1a32 lib/pico-sdk: Update to version 2.1.0.
Brings in support for Pico 2 W, among other things.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2025-03-04 19:38:19 +01:00
Damien George
ecfdd5d6f9 all: Bump version to 1.24.1.
Signed-off-by: Damien George <damien@micropython.org>
2024-11-29 23:53:11 +11:00
Angus Gratton
564ef28ad2 py/objfloat: Workaround non-constant NAN definition on Windows MSVC.
Recent MSVC versions have changed the definition of NAN to a non-constant
expression!  This is a bug, C standard says it should be a constant.

Good explanation and workaround at: https://stackoverflow.com/a/79199887

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-28 23:56:21 +11:00
robert-hh
7118942a8c nrf/drivers/ticker: Reset slow ticker callback count on soft reboot.
The micro:bit board (and probably other boards using the music or display
module) locked up on soft reboot.  Reason was a buffer overflow caused by
an index counter, which was not reset on soft_reboot.

That's fixed in this commit.  Tested with a micro:bit board, performing a
series of soft reboots.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-11-28 23:08:33 +11:00
Corran Webster
948863c0b8 extmod/modframebuf: Fix 0 radius bug in FrameBuffer.ellipse.
This fixes a bug in FrameBuffer.ellipse where it goes into an infinite loop
if both radii are 0.

This fixes the bug with a simple pre-check to see if both radii are 0, and
in that case sets a single pixel at the center. This is consistent with the
behaviour of the method when called with just one of the radii set to 0,
where it will draw a horizontal or vertical line of 1 pixel width.

The pixel is set with setpixel_checked so it should handle out-of-bounds
drawing correctly.

This fix also includes three new tests: one for the default behaviour, one
for drawing out-of-bounds, and one for when the sector mask is 0.

Fixes issue #16053.

Signed-off-by: Corran Webster <cwebster@unital.dev>
2024-11-28 23:08:29 +11:00
Angus Gratton
33f50d4f20 esp32: Fix machine.TouchPad startup on ESP32-S2 and S3.
Closes #13178.

TouchPad confirmed working on both chips, and fixes the the ESP32-S3
reading constant max value. Was unable to reproduce the bug on ESP32-S2 but
this may be due to my test setup, and it still works with the fix.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-28 23:08:26 +11:00
Angus Gratton
eb0027b82f esp32: Use hardware version for touchpad macro defines.
ESP32 has hardware V1 and S2/S3 has V2, and future chips
may have different versions.

This should still compile to the same binary before and after.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-28 23:08:22 +11:00
Angus Gratton
03bc561edb esp32: Fix setting WLAN channel in AP mode.
- Previously the call to esp_wifi_set_channel() would be immediately
  overridden by calling esp_wifi_config(...) with the previous channel set.

- AP interface doesn't seem to need more than esp_wifi_config(...) to work.
  It will automatically configure 40MHz bandwidth and place the secondary
  channel using similar logic to what was being explicitly calculated here.

- However, calling esp_wifi_set_channel() on the STA interface is necessary
  if using this interface with ESP-NOW (without connecting to an AP). So
  the esp_wifi_set_channel() call is kept in for this purpose. Without
  this, tests/multi_espnow/70_channel.py fails.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-28 23:08:18 +11:00
Angus Gratton
49b83ed44a extmod/network_cyw43: Allow configuring active AP interface.
Configuring the AP for cyw43 writes to some buffers that are only sent to
the modem when the interface is brought up. This means you can't configure
the AP after calling active(True), the new settings seem to be accepted but
the radio doesn't change.

This is different to the WLAN behaviour on other ports. The esp8266 port
requires calling active(True) on the AP before configuring, even.

Fix this by bouncing the AP interface after a config change, if it's
active. Configuring with active(False) still works the same as before.

Adds a static variable to track interface active state, rather than relying
on the LWIP interface state. This is because the interface state is updated
by a driver callback and there's a race: if code calls active(True) and
then config(a=b) then the driver doesn't know it's active yet and the
changes aren't correctly applied.

It is possible this pattern will cause the AP to come up briefly with the
default "PICOabcd" SSID before being reconfigured, however (due to the
aforementioned race condition) it seems like this may not happen at all
before the new config is applied.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-20 14:44:53 +11:00
Damien George
4f4d683ea5 extmod/network_cyw43: Fix uninitialised variable in status('stations').
The `num_stas` was uninitialised and if it happened to take the value 0
then no results were returned.  It now has the correct maximum value.

Signed-off-by: Damien George <damien@micropython.org>
2024-11-20 14:27:16 +11:00
Angus Gratton
67f893852a extmod/network_cyw43: Fix isconnected() result on AP interface.
This function is documented to return True if any stations are connected to
the AP. Without this fix it returns True whenever the driver has brought
the AP interface up.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-20 14:27:11 +11:00
Damien George
20a6d82872 extmod/vfs_blockdev: Support bool return from Python read/write blocks.
Commit f4ab9d9247 inadvertently broke some
Python block devices, for example esp32 and stm32 SDCard classes.  Those
classes return a bool from their `readblocks` and `writeblocks` methods
instead of an integer errno code.  With that change, both `False` and
`True` return values are now be interpreted as non-zero and hence the block
device call fails.

The fix in this commit is to allow a bool and explicitly convert `True` to
0 and `False` to `-MP_EIO`.

Signed-off-by: Damien George <damien@micropython.org>
2024-11-18 23:27:13 +11:00
Damien George
0c580f71ae esp32/modsocket: Fix getaddrinfo hints to set AI_CANONNAME.
Because the `ai_canonname` field is subsequently used.

ESP32_GENERIC_S3 (at least) crashes with IDF 5.2.3 without this set.

Signed-off-by: Damien George <damien@micropython.org>
2024-11-18 23:27:13 +11:00
Damien George
4e78c611b4 tools/mpremote: Support trailing slash on dest for non-recursive copy.
This fixes a regression in db59e55fe7: prior
to that commit `mpremote` supported trailing slashes on the destination of
a normal (non-recursive) copy.

Add back support for that, with the semantics that a trailing slash
requires the destination to be an existing directory.

Also add a test for this.

Signed-off-by: Damien George <damien@micropython.org>
2024-11-18 23:27:13 +11:00
Damien George
159b54b7da tools/mpremote: Add test for forced copy.
Signed-off-by: Damien George <damien@micropython.org>
2024-11-18 23:27:13 +11:00
Damien George
c1a85bb6de tools/mpremote: Make sure stdout and stderr output appear in order.
mpremote error messages now go to stderr, so make sure stdout is flushed
before printing them.

Also update the test runner to capture error messages.

Signed-off-by: Damien George <damien@micropython.org>
2024-11-18 23:27:13 +11:00
Angus Gratton
72799f9973 esp32: Workaround native code execution crash on ESP32-S2.
Seemingly ESP-IDF incorrectly marks RTC FAST memory region
as MALLOC_CAP_EXEC on ESP32-S2 when it isn't. This memory is
the lowest priority, so it only is returned if D/IRAM is exhausted.

Apply this workaround to treat the allocation as failed if it gives us
non-executable RAM back, rather than crashing.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-18 23:27:13 +11:00
Angus Gratton
164c549248 esp32/machine_pwm: Restore PWM support for ESP-IDF v5.0.x and v5.1.x.
The cleanup in 548babf8 relies on some functions not available in older
ESP-IDF. Temporarily restore them, until we drop support for ESP-IDF <5.2.

PWM functionality should end up the same regardless of ESP-IDF version, and
also no different from MicroPython V1.23.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-11-18 23:27:13 +11:00
Damien George
6f327684b7 extmod/modlwip: Fix IGMP address type when IPv6 is enabled.
This was missed in 628abf8f25.  The the bug
was that, when IPv6 is enabled, the `sizeof(ip_addr_t)` is much larger than
IPv4 size, which is what's needed for IGMP addressing.

Fixes issue #16100.

Signed-off-by: Damien George <damien@micropython.org>
2024-11-18 23:27:13 +11:00
Jan Sturm
a7d3bc2308 py/objdeque: Fix buffer overflow in deque_subscr.
In `deque_subscr()`, if `index_val` equals `self->alloc`, the index
correction `index_val -= self->alloc` does not execute, leading to an
out-of-bounds access in `self->items[index_val]`.

The fix in this commit ensures that the index correction is applied
whenever `index_val >= self->alloc`, preventing access beyond the allocated
buffer size.

Signed-off-by: Jan Sturm <jansturm92@googlemail.com>
2024-11-18 23:27:13 +11:00
Alessandro Gatti
c0afff8f22 pic16bit: Make it build with recent XC16 versions.
The PIC16 port didn't catch up with the other ports, so it required a bit
of work to make it build with the latest version of XC16.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-11-18 23:27:13 +11:00
Andrew Leech
785c92df76 esp32/machine_pwm: Use IDF functions to calculate resolution correctly.
This commit fixes PWM configuration across C3, C6, S2 and S3 chips, which
was broken by 6d799378ba.  Without this fix
the PWM frequency is limited to a maximum of 2446Hz (on S2 at least).

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-11-18 23:27:13 +11:00
Glenn Moloney
5c7ac55232 tools/mpremote: Fix UnboundLocalError in Transport.fs_writefile().
The variable `written` was being used before it was defined in the
`fs_writefile()` method of the Transport class.  This was causing an
`UnboundLocalError` to be raised when the `progress_callback` was not
provided.

Fixes issue #16084.

Signed-off-by: Glenn Moloney <glenn.moloney@gmail.com>
2024-11-18 23:27:13 +11:00
Damien George
f212bbe837 all: Bump version to 1.24.0.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-26 01:43:23 +11:00
Damien George
18c9abc329 lib/micropython-lib: Update submodule to latest.
This brings in:
- requests improvements with overriding headers
- use non-u versions of built-in modules, including asyncio
- fix to logging so StreamHandler calls parent constructor
- various fixes to usb-device packages
- fixes to lora sx126x and sx127x drivers
- improvements to unix-ffi/sqlite3
- support additional gap_connect arguments in aioble

Signed-off-by: Damien George <damien@micropython.org>
2024-10-25 01:26:58 +11:00
iabdalkader
4c54335195 stm32/boards/ARDUINO_OPTA: Add Opta expansion module.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-10-25 01:19:54 +11:00
iabdalkader
57bc98f499 stm32/boards/ARDUINO_NICLA_VISION: Add SE05x driver.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-10-25 01:19:48 +11:00
iabdalkader
28009a78cf stm32/boards/ARDUINO_PORTENTA_H7: Add SE05x driver.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-10-25 01:19:06 +11:00
iabdalkader
bab6a016b3 lib/arduino-lib: Update submodule.
Changes:
- Add ISO7816, APDU and SE05x package.
- Add support for Opta Expansion protocol.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-10-25 01:18:33 +11:00
iabdalkader
68f1c20145 extmod/modtls_mbedtls: Support alternate sign callbacks in Python.
This commit enables the implementation of alternative mbedTLS cryptography
functions, such as ECDSA sign and verify, in pure Python.  Alternative
functions are implemented in Python callbacks, that get invoked from
wrapper functions when needed.  The callback can return None to fall back
to the default mbedTLS function.

A common use case for this feature is with secure elements that have
drivers implemented in Python.  Currently, only the ECDSA alternate sign
function wrapper is implemented.

Tested signing with a private EC key stored on an NXP SE05x secure element.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-10-25 01:16:06 +11:00
iabdalkader
2644f577f1 extmod/modtls_mbedtls: Add a thread-global ptr for current SSL context.
This is necessary for mbedTLS callbacks that do not carry any user state,
so those callbacks can be customised per SSL context.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-10-25 01:12:36 +11:00
Damien George
09ea901317 tests/extmod: Add test to compare time_ns with time.
They should be close together.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-24 23:24:09 +11:00
Damien George
1ec0c9b886 tests/extmod: Use time_ns instead of time in lfs mtime test.
Because VfsLfs2 uses time_ns to create timestamps for files, and for the
test to give consistent results it also needs to use this same function.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-24 23:24:09 +11:00
Damien George
120ac0f8d2 rp2/modmachine: Re-sync time_ns offset when coming out of lightsleep.
Prior to this fix, `tests/extmod/vfs_lfs_mtime.py` would fail when run
after the `tests/ports/rp2/rp2_lightsleep.py` test, because
`time.time_ns()` would have a large and constant offset from `time.time()`.

Fix this by re-syncing the time-ns offset when coming out of lightsleep.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-24 23:24:09 +11:00
Damien George
ca6aed7649 tests/extmod: Fix access of RTC class in machine.RTC test.
This previously passed on some targets that automatically import the
`machine` module in `boot.py`.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-24 16:29:43 +11:00
Damien George
6d98280fda tests/extmod: Add a simple test for machine.RTC.
Tests at least that the datetime can be set and get correctly.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-24 11:43:03 +11:00
Damien George
47741e2757 rp2/datetime_patch: Fix year and month offset for mktime wrapper.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-24 11:22:59 +11:00
Damien George
43bd57f94b shared/timeutils: Document the range of year/month/day etc input values.
These differ to, eg, the standard `mktime()` function.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-24 11:22:22 +11:00
Jared Hancock
078ead24f3 extmod/network_wiznet5k: Reset mDNS when interface is brought up.
The LwIP interface is removed in wiznet5k_deinit() which is called as part
of the init sequence.  Therefore, if using mDNS, then the interface will
need to be re-added when bringing the interface up.

Additionally, this allows to set the hostname from MicroPython code prior
to bringing the interface up and mDNS responding to the (new) hostname.
This allows the hostname to be configured and saved on the flash or be
based on dynamic information such as the MAC or unique_id().

Signed-off-by: Jared Hancock <jared.hancock@centeredsolutions.com>
2024-10-23 16:29:28 +11:00
Damien George
3f54e5dff2 tests/extmod: Support esp32,mimxrt,stm32,samd ports in UART TX test.
Getting this test running on stm32- and mimxrt-based boards requires adding
a small delay after constructing the UART so that the initial idle frame
has time to be transmitted before the test starts.

Also, the timing margin needs to account for an additional 1-bit worth of
time on some MCUs.

Thanks to @robert-hh for the esp32, mimxrt and samd settings.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 22:21:17 +11:00
Alessandro Gatti
6328958a39 rp2/mpconfigport: Leave callable pointers alone on RV32.
The port configuration file tagged callable pointers' LSB on both Arm
and RISC-V variants.  This is needed on Arm due to Thumb/Thumb2
code addresses having their LSB set, but on RISC-V this is not required.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-10-22 15:01:53 +11:00
Plaque FCC
324871f380 qemu/mcu/rv32: Fix test of mcause value in lookup_cause.
Signed-off-by: Plaque FCC <plaque-fcc@github>
2024-10-22 14:52:01 +11:00
Volodymyr Shymanskyy
8fef67bda5 esp32/modmachine: Allow building with USB CDC disabled.
Signed-off-by: Volodymyr Shymanskyy <vshymanskyi@gmail.com>
2024-10-22 14:45:51 +11:00
Damien George
0646177997 tests/extmod: Make invalid-blockdev test work consistently on all ports.
Some ports (eg stm32) configure the FAT driver differently (eg with
multi-partition support) and that leads to a slightly different sequence of
block reads, compared to other configurations (eg rp2).

Comment out the printing in `readblocks()` so the tests are deterministic
(the printing is still useful for debugging).

Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 14:32:51 +11:00
Damien George
f7abb52847 tests/run-tests.py: Skip large viper test on esp8266.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 14:31:13 +11:00
Damien George
52f2ba5677 tests/micropython: Tweak ringio test for targets with terse errors.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 14:31:13 +11:00
Damien George
1e3b24238e tests/extmod: Adjust ssl/tls tests to run on targets with axTLS.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 14:31:13 +11:00
Damien George
7d442373af tests/extmod: Config SPI test for esp8266 and skip SoftTimer test.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 14:31:13 +11:00
Corran Webster
d1574de3b6 extmod/modframebuf: Fix FrameBuffer size check for stride corner-cases.
This is a fix for issue #15944, and handles corner cases in the FrameBuffer
code when using stride values where the last line's stride may extend past
the end of the underlying buffer.  This commit includes extra tests for
these corner cases.

For example a GS8 format FrameBuffer with a width of 8, height of 2 and
stride of 10 should be able to fit into a buffer of size 18 (10 bytes for
the first horizontal line, and 8 bytes for the second -- the full 10 bytes
are not needed).

Similarly a 1 by 9 FrameBuffer in MONO_VLSB format with a stride of 10
should be able to fit into a buffer of length 11 (10 bytes for the first
8 lines, and then one byte for the 9th line.

Being able to do this is particularly important when cropping the corner of
an existing FrameBuffer, either to copy a sprite or to clip drawing.

Signed-off-by: Corran Webster <cwebster@unital.dev>
2024-10-22 13:05:31 +11:00
Damien George
7ed480fc6f Revert "stm32/machine_uart: Allow changing only the baudrate."
This reverts commit c94a3205b0.

The idea behind this reverted commit was that it allowed to reconfigure the
UART to change only the baudrate, which is important in the context of a
PPP connection where the baudrate may be changed as part of the protocol.
Also, other ports like the rp2 port have this behaviour, where individual
parameters of the UART can be changed with the `.init()` method.

But this commit was no good for a few reasons:

1. It's a subtle breaking change to the UART API, because existing code
   that constructs or initialises a UART with just the baudrate would
   expect all other parameters to be reset to their defaults.  But with
   this commit those parameters would remain unchanged.

2. Constructing a UART like `UART(1, 9600)` also hits this code path of
   only changing the baudrate and does not reset other parameters, which is
   unexpected.

3. It doesn't support setting the baudrate via keyword, eg
   `UART.init(baudrate=9600)`.

4. The `timeout_char` field is not updated when changing only the baudrate,
   which can lead to unexpected timeouts when reading/writing.

Due to point (4), this commit broke the `tests/ports/stm32/uart.py` test,
the `uart.writechar(1)` has a timeout because the `uart.init(2400)` does
not set the `timeout_char` for the new baudrate.

Points (2)-(4) could be fixed, but point (1) (being a breaking change)
would remain as an issue.  So the commit is reverted.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 11:50:05 +11:00
Damien George
97af1001ae rp2/machine_uart: Make it so TX is done only when no longer busy.
Prior to this commit, when flushing a UART on the rp2 port, it returns just
before the last character is sent out the wire.

Fix this by waiting until the BUSY flag is cleared.

This also fixes the behaviour of `UART.txdone()` to return `True` only when
the last byte has gone out.

Updated docs and tests to match.  The test now checks that UART TX time is
very close to the expected time (prior, it was just testing that the TX
time was less than the expected time).

Signed-off-by: Damien George <damien@micropython.org>
2024-10-22 10:17:05 +11:00
Damien George
1b89c503db py/objtype: Don't delegate lookup of descriptor methods to __getattr__.
When descriptors are enabled, lookup of the `__get__`, `__set__` and
`__delete__` descriptor methods should not be delegated to `__getattr__`.
That follows CPython behaviour.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-16 15:03:30 +11:00
Andrew Leech
3fecab58a0 esp32/mphalport: Always poll stdin ring-buffer to include UART use.
This fixes a regression introduced in commit
4247921c4e, where this ring-buffer polling
was accidentally put inside the `#if MICROPY_HW_ESP_USB_SERIAL_JTAG`.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-16 14:50:11 +11:00
Damien George
838f21298a unix/main: Add --version command-line option.
CPython also has this option.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 14:44:10 +11:00
Damien George
51663b9aa7 rp2/machine_uart: Clear timeout_char when UART is first constructed.
Otherwise a previous value of `timeout_char` may be left over after a soft
reset.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:23:06 +11:00
Damien George
b33f64792f tests/run-tests.py: Only run inlineasm tests on rp2 ARM targets.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:23:06 +11:00
Damien George
b42bb911c6 tests/ports/rp2: Update lightsleep/machine_idle to skip on RP2350.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:23:06 +11:00
Damien George
651b63cd79 tests/ports/rp2: Add simple rp2-specific UART test.
To test construction of UART instances.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:23:06 +11:00
Damien George
fda7ae83a8 tests/ports/rp2: Update DMA test to work on RP2350.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:21:10 +11:00
Damien George
f9cebe676e tools/ci.sh: Add RPI_PICO2 to CI.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:21:10 +11:00
Peter Harper
e32e13f7e4 rp2/boards/RPI_PICO2: Add new RPI_PICO2 board definition.
This is the same form-factor as the Pico but with an RP2350.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:20:12 +11:00
Damien George
137e9e8c79 rp2/main: Set CPU frequency to default for the MCU.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:20:12 +11:00
Phil Howard
27904ae4b9 rp2/machine_pwm: Add RP2350 slices to machine.PWM.
Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-10-15 12:19:52 +11:00
Angus Gratton
8cc7c64d01 rp2: Workaround pico_aon_timer timezone binary size increase.
Provide stub implementations of localtime_r() and mktime() to avoid
code size increase.

Reported upstream at https://github.com/raspberrypi/pico-sdk/issues/1810

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-10-15 12:18:53 +11:00
Damien George
fa15ae4503 rp2/machine_bitstream: Implement bitstream for RISC-V using mcycle.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:18:51 +11:00
Damien George
ea2eed1b23 rp2/mphalport: Implement mp_hal_ticks_cpu for RISCV using mcycle.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:18:32 +11:00
Dryw Wade
957cea23d5 rp2/machine_uart: Allow new TX/RX pins on RP2350.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:18:32 +11:00
Dryw Wade
7a78e5ae7c rp2/machine_bitstream: Set SysTick reset value.
In case it doesn't have the correct value.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:18:29 +11:00
Damien George
f2f08ef2d9 rp2/Makefile: Allow CMAKE_ARGS to be set by user.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:16:46 +11:00
Damien George
4fc6cf9141 rp2: Add support for RP2350 in RISCV mode.
As part of this change, the RV32I native emitter is enabled on RISCV
board variants.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:16:46 +11:00
Phil Howard
34e463d861 rp2/machine_adc: Add ADC support for RP2350B.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:16:46 +11:00
Peter Harper
d0bc42796b rp2/clocks_extra: Update runtime_clocks_init based on new pico-sdk.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:15:48 +11:00
Phil Howard
57f4cabff9 rp2/machine_pin: Generalise gpio_irq handler for pins >32.
Fix the gpio_irq function so that it looks at all six iobank0_hw->intr[n]
registers, for up to 48 IOs.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-10-15 12:14:59 +11:00
Peter Harper
733052f6b9 rp2/machine_pin: Use 64-bit gpio functions to allow gpios >=32 to work.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:14:25 +11:00
Peter Harper
4af09de19c rp2/boards/make-pins.py: Pass num-gpios/num-ext-gpios into make-pins.
NUM_GPIOS amd NUM_EXT_GPIOS are currently hardcoded in make-pins.py, which
makes it difficult to support SoCs with different pin count.

This commit generalises make-pins.py by passing in the pin count in via the
new arguments `--num-gpios` and `--num-ext-gpios`.  These default to the
current values supported by Pico, namely 30/10.  This can be changed with
PICO_NUM_GPIOS and PICO_NUM_EXT_GPIOS in `mpconfigboard.cmake`.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:12:04 +11:00
Phil Howard
e6093c0fbd rp2/rp2_pio: Add support for RP2350A/B variants in PIO interface.
Add support for 32 and 48 pin variants of RP2350.

Add new `PIO.gpio_base()` method, mirroring the Pico SDK.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:09:48 +11:00
Damien George
a3d1c59ca3 rp2/machine_pin: Move decl of machine_pin_obj_table to public header.
So other code can include `machine_pin.h` and use the pin name macros such
as `pin_GPIO0`.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 12:09:48 +11:00
Phil Howard
6d39418f69 rp2: Add support for 48-pin RP2350 variant.
Update NUM_GPIOS to match NUM_BANK0_GPIOS, and increase bit-width of
variables that store pin numbers.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-10-15 12:08:39 +11:00
Peter Harper
d2c85c74da rp2: Integrate RP2350 and use aon_timer instead of rtc API.
This commit separates various build settings and include files that are
specific to RP2040 and RP2350, and uses the aon_timer interface instead of
rtc, to work across both MCU variants.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-10-15 12:07:59 +11:00
Peter Harper
27aeade832 rp2/rp2_dma: Generalise DMA for RP2350.
Two new bits were added to the ctrl register, and existing bits were
shifted, so use DMA_CH0_CTRL_TRIG_xxx constants to generalise the code.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 11:57:06 +11:00
Peter Harper
d1423ef7a2 rp2/modmachine: Implement lightsleep for RP2350.
This isn't fully working, the CPU often wakes up early.  That will be fixed
when a newer version of pico-sdk is released.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 11:56:27 +11:00
Peter Harper
c90d996c9d rp2: Update custom linker scripts for new pico-sdk.
Signed-off-by: Phil Howard <phil@gadgetoid.com>
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 11:51:56 +11:00
Peter Harper
815d6a131d rp2/mpconfigport: Set MCU name for RP2350.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 11:51:56 +11:00
Damien George
70a884d6ec lib/pico-sdk: Update to version 2.0.0.
Adds support for the new RP2350 MCU.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 11:51:56 +11:00
Phil Howard
525fce7170 py/usermod.cmake: Check target exists in usermod_gather_sources.
Check a target exists before accessing properties.  Otherwise
usermod_gather_sources would recurse into garbage property names and break.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-10-15 11:51:56 +11:00
Ayush Singh
fa942d532f zephyr/boards: Add support for BeagleConnect Freedom.
Enable the following capabilities: I2C, SPI, FLASH.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
2024-10-15 11:44:42 +11:00
Damien George
d92694c3e8 tools: Only issue a single Ctrl-C when entering raw REPL.
A long time ago when there was only the `stm` port, Ctrl-C would trigger a
preemptive NLR jump to break out of running code.  Then in commit
124df6f8d0 a more general approach to
asynchronous `KeyboardInterrupt` exceptions was implemented, and `stmhal`
supported both approaches, with the general (soft) interrupt taking
priority.

Then in commit bc1488a05f `pyboard.py` was
updated with a corresponding change to make it issue a double Ctrl-C to
break out of any existing code when entering the raw REPL (two Ctrl-C
characters were sent in order to more reliably trigger the preemptive NLR
jump).

No other port has preemptive NLR jumps and so a double Ctrl-C doesn't
really behave any differently to a single Ctrl-C: with USB CDC the double
Ctrl-C would most likely be in the same USB packet and so processed in the
same low-level USB callback, so it's just setting the keyboard interrupt
flag twice in a row.  The VM/runtime then just sees one keyboard interrupt
and acts as though only one Ctrl-C was sent.

This commit changes the double Ctrl-C to a single Ctrl-C in `pyboard.py`
and `mpremote`.  That keeps things as simple as they need to be.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 11:40:08 +11:00
Damien George
7746785035 tests/run-tests.py: Wait for soft reset if a target skips a test.
Commit 69c25ea865 made raising `SystemExit`
do a soft reset (on bare-metal targets).  This means that any test which is
skipped by a target (by raising `SystemExit`) will trigger a soft reset on
that target, and then it must execute its startup code, such as `boot.py`.

If the timing is right, this startup code can be unintentionally
interrupted by the test runner when preparing the next test, because the
test runner enters the raw REPL again via a Ctrl-C Ctrl-A ctrl-D sequence
(in `Pyboard.enter_raw_repl()`).

When this happens (`boot.py` is interrupted) the target may not be set up
correctly, and it may (in the case of stm32 boards) flash LEDs and take
extra time, slowing down the test run.

Fix this by explicitly waiting for the target to finish its soft reset when
it skips a test.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 11:23:07 +11:00
Damien George
1223fa92f1 renesas-ra/pendsv: Remove preemptive keyboard interrupt via PendSV.
Following the same change to the stm32 port.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 10:32:24 +11:00
Damien George
ece950d9be stm32/pendsv: Remove preemptive keyboard interrupt via PendSV.
Since the very beginning, the stm32 port (first called stm, then stmhal now
stm32) has had a special keyboard interrupt feature which works by using
PendSV to break out of any running code.  This preemptive ctrl-C was added
long ago in commit 01156d510c.

The stm32 port still uses that code, and current does this:

- If ctrl-C is received on UART or USB then `mp_sched_keyboard_interrupt()`
  is called (like all other ports) to set a flag for the VM to see, and
  then the VM (or any loop calling `mp_handle_pending(true)`) will
  eventually handle the `KeyboardInterrupt` exception, raising it via NLR.

- If another ctrl-C is received while the existing scheduled keyboard
  interrupt is still pending (ie the VM has not yet processed it) then a
  special hard NLR jump will activate, that preempts the calling code.
  Within the PendSV interrupt the stack is adjusted and an NLR jump is made
  to the most recent `nlr_push()` location.  This is like a normal NLR
  except it is called from an interrupt context and completely annihilates
  the code that was interrupted by the IRQ.

The reason for the preemptive interrupt was to handle ctrl-C before the VM
was able to handle it.  Eventually a mechanism (that's in use today by all
ports) was added to the VM and runtime to be able to check for pending
interrupts.  Then the stm32 port was updated to use this mechanism, with a
fallback to the old preemptive way if a second ctrl-C was received (without
the first one being processed).

This preemptive NLR jump is problematic because it can interrupt
long-running instructions (eg store multiple, usually used at the end of a
function to restore registers and return).  If such an instruction is
interrupted the CPU remembers that with some flags, and can resume the
long-running instruction when the interrupt finishes.  But the preemptive
NLR does a long jump to different code at thread level and so the
long-running interrupt is never resumed.  This leads to a CPU fault.

This fault has been previously reported in issues #3807 and #3842 (see also
issue #294).  It's now possible to easily reproduce this problem, since
commit 69c25ea865.  Running the test suite
over and over again on any stm32 board will eventually crash the board (it
can happen on a PYBv1.x, but it happens more regularly on PYBD-SF2/6).

The point is, a skipped test now soft resets the board and so the board
must run `boot.py` again.  The test runner may then interrupt the execution
of `boot.py` with the double-ctrl-C that it sends (in `tools/pyboard.py`,
`enter_raw_repl()`) in order to get the board into a known good state for
the next test.  If the timing is right, this can trigger the preemptive
PendSV in an unfortunate location and hard fault the board.

The fix in this commit is to just remove the preemptive NLR jump feature.
No other port has this feature and it's not needed, ctrl-C works very well
on those ports.  Preemptive NLR jump is a very dangerous thing (eg it may
interrupt and break out of an external SPI flash operation when reading
code from a filesystem) and is obviously buggy.

With this commit, stm32 borads no longer hard fault when running the test
suite (but it does leave an issue, the tests can still interrupt `boot.py`
with a single ctrl-C; that will be fixed separately).

An alternative to this commit would be to clear the CPU state for the
long-running instruction as suggested in issue #3842.  But it's much
simpler to just remove this code, which is now unnecessary and can have
other problems as per issue #294.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-15 10:32:14 +11:00
Damien George
44ed1c20ce esp32: Disable hardware stack protection on ESP32-C6.
The same as fee9d66e3a but for C6.

Fixes issue #15667.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-11 12:53:10 +11:00
Angus Gratton
82e69df33e esp32: Apply the LWIP active TCP socket limit.
This is a workaround for a bug in ESP-IDF where the configuration setting
for maximum active TCP sockets (PCBs) is not applied.

Fixes cases where a lot of short-lived TCP connections can cause:

- Excessive memory usage (unbounded number of sockets in TIME-WAIT).
- Much higher risk of stalled connections due to repeated port numbers. The
  maximum number of active TCP PCBs is reduced from 16 to 12 to further
  reduce this risk (trade-off against possibility of TIME-WAIT
  Assassination as described in RFC1337).

This is not a watertight fix for the second point: a peer can still reuse a
port number while a previous socket is in TIME-WAIT, and LWIP will reject
that connection (in an RFC compliant way) causing the peer to stall.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-10-10 17:55:03 +11:00
Angus Gratton
05ac69329d esp32: Fix hang in taskYIELD() on riscv CPUs when IRQs disabled.
Regression introduced in 337742f.

The hang occurs because the esp32 port was calling "from ISR" port-layer
functions to set/clear the interrupt mask. FreeRTOS kernel therefore
doesn't know the CPU is in a critical section. In taskYIELD() the riscv
port layer blocks after yielding until it knows the yield has happened, and
would block indefinitely if IRQs are disabled (until INT WDT triggers).

Moving to the "public" portENTER_CRITICAL/portEXIT_CRITICAL API means that
FreeRTOS knows we're in a critical section and can react accordingly.

Adds a regression test for this case (should be safe to run on all ports).

On single core CPUs, this should result in almost exactly the same
behaviour apart from fixing this case.

On dual core CPUs, we now have cross-CPU mutual exclusion for atomic
sections. This also shouldn't change anything, mostly because all the code
which enters an atomic section runs on the same CPU. If it does change
something, it will be to fix a thread safety bug.

There is some risk that this change triggers a FreeRTOS crash where there
is a call to a blocking FreeRTOS API with interrupts disabled. Previously
this code might have worked, but was probably thread unsafe and would have
hung in some circumstances.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-10-10 10:59:51 +11:00
Damien George
197becbdcc tests: Tweak machine SPI and UART tests to work with esp32c6.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-09 23:34:27 +11:00
Andrew Leech
55dc482d3e esp32/sdkconfig: Disable PMP_IDRAM_SPLIT to fix native emit support.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-09 23:34:27 +11:00
Matt Trentini
ce397d85af esp32/boards/UM_TINYC6: Add new UM C6 board definition.
Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-10-09 23:32:47 +11:00
Matt Trentini
ee92198c8a esp32/boards/M5STACK_NANOC6: Add new M5Stack C6 board definition.
Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-10-09 23:32:26 +11:00
Andrew Leech
1bd312d737 esp32/boards/ESP32_GENERIC_C6: Add new generic esp32c6 board.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-09 23:32:10 +11:00
Andrew Leech
2f79854337 esp32/Makefile: Only set port & baud for jobs that access hardware.
In idf v5.2.1 if the port flag is set it's validated even on jobs that
don't access hardware like clean.  This causes the job to fail if device
isn't connected.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-09 23:31:54 +11:00
dmfaria
5aa115a4bc esp32/adc: Set ADC to 12bit by default on esp32c6.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-09 23:31:21 +11:00
Andrea Milazzo
68e95c73d3 esp32/machine_uart: Add support for LP_UART.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-09 23:31:16 +11:00
IhorNehrutsa
a0f82a5f39 esp32/modesp32: Make gpio_deep_sleep_hold optional.
Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2024-10-09 23:30:58 +11:00
IhorNehrutsa
958d20f3c0 esp32/machine_timer: Generalise timer clock configuration.
Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2024-10-09 23:30:48 +11:00
IhorNehrutsa
32a2c87813 esp32/machine_adc: Make ADC 2 optional.
Signed-off-by: IhorNehrutsa <IhorNehrutsa@gmail.com>
2024-10-09 23:30:20 +11:00
Andrew Leech
6d799378ba esp32: Add support for esp32c6.
This commit adds general support for ESP32-C6 SoCs.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-09 23:29:38 +11:00
Damien George
e5eeaa7df8 docs/reference/mpremote: Update docs to mention new features.
Signed-off-by: Damien George <damien@micropython.org>
2024-10-09 16:39:06 +11:00
Damien George
a25b6b9c65 tools/mpremote: Add option to force copy.
This adds a -f/--force option to the "cp" command, which forces
unconditional copies, in particular does not check the hash.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-09 16:39:06 +11:00
Jim Mussared
6461ffd9d1 tools/mpremote: Add initial regression tests for mpremote.
These tests are specifically for the command-line interface and cover:
 - resume/soft-reset/connect/disconnect
 - mount
 - fs cp,touch,mkdir,cat,sha256sum,rm,rmdir
 - eval/exec/run

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
2024-10-09 16:39:00 +11:00
Jim Mussared
dd6f78f014 tools/mpremote: Improve error output.
Makes the filesystem command give standard error messages rather than
just printing the exception from the device.

Makes the distinction between CommandError and TransportError clearer.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2024-10-09 16:38:08 +11:00
Jim Mussared
6f8157d880 tools/mpremote: Add hashing ability and use for recursive copy.
Changes in this commit:
- Adds transport API `fs_hashfile` to compute the hash of a file with given
  algorithm.
- Adds commands `mpremote <...>sum file` to compute and print hashes of
  various algorithms.
- Adds shortcut `mpremote sha256sum file`.
- Uses the hash computation to improve speed of recursive file copy to
  avoid copying a file where the target is identical.

For recursive copy, if possible it will use the board's support (e.g.
built-in hashlib or hashlib from micropython-lib), but will fall back to
downloading the file and using the local implementation.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
2024-10-09 16:35:46 +11:00
Jim Mussared
db59e55fe7 tools/mpremote: Make filesystem commands use transport API.
This introduces a Python filesystem API on `Transport` that is implemented
entirely with eval/exec provided by the underlying transport subclass.

Updates existing mpremote filesystem commands (and `edit) to use this API.

Also re-implements recursive `cp` to allow arbitrary source / destination.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
2024-10-09 16:12:30 +11:00
Jim Mussared
1091021995 tools/mpremote: Make eval parse by default.
This is a step towards making the transport expose a Python API rather than
functions that mostly print to stdout.

Most use cases of `transport.eval()` are to get some state back from the
device, so have it return as a value directly by default.

Updates uses of `transport.eval()` to remove the parse argument where it
now isn't needed, make the `rtc` command use eval/exec, and update the
`mip` command to use eval's parsing.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2024-10-09 15:56:17 +11:00
stijn
6835743dcc extmod/vfs_posix_file: Skip flush of tty handles in msvc debug builds.
In MSVC debug builds with debug error reporting set to showing a dialog (to
allow attaching the debugger), any application which imports the logging
module and leaves the default handlers would result in this dialog because
logging.shutdown is called at exit and that flushes the default handler
which has stderr as its stream.

This commit fixes that by not fsync'ing stdin/out/err.

Also adds a comment related to checking whether a file is stdin/out/err,
which is difficult to fix properly.

Signed-off-by: stijn <stijn@ignitron.net>
2024-10-09 15:03:07 +11:00
Damien George
d50e36e7e4 ports: Include py/mphal.h instead of mphalport.h.
The `mphalport.h` header should not be included directly, rather
`py/mphal.h` should be used.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-09 14:39:34 +11:00
Andrew Leech
c2eebe0609 tests/README: Update instructions for key/cert pair usage on device.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-09 14:37:59 +11:00
stijn
338df1ae35 py/objtype: Allow passing keyword arguments to native base __init__.
Allowing passing keyword arguments to a native base's __init__, i.e.
`make_new` in the C code.  Previously only positional arguments were
allowed.

The main trade-off in this commit is that every call to the native base's
`make_new` is now going to be preceded by a call to
`mp_map_init_fixed_table` even though most of what that does is unused and
instead it merely serves as a way to pass the number of keyword arguments.

Fixes issue #15465.

Signed-off-by: stijn <stijn@ignitron.net>
2024-10-07 11:37:52 +11:00
Andrew Leech
548f88d2bd shared/tinyusb: Wake main task if needed at end of USB ISR.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-07 11:06:57 +11:00
Andrew Leech
11bc7d0fc1 esp32/boards: Update ARDUINO_NANO_ESP32 USB configuration.
The custom line state handling is no longer needed as MicroPython runs it
directly now.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-07 11:06:57 +11:00
Andrew Leech
386771e052 esp32/Makefile: Allow auto-port selection if not passed on cmdline.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-07 11:06:57 +11:00
Andrew Leech
5ae622ef7b esp32: Add automatic bootloader handling for S2 and S3.
Enables support for the ESP standard DTR/RTS based reboot to bootloader.

Switches from OTG to Serial/Jtag mode to workaround issue discussed
in: https://github.com/espressif/arduino-esp32/issues/6762

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-07 11:06:57 +11:00
Andrew Leech
641f60045f shared/tinyusb: Remove MICROPY_HW_USB_EXTERNAL_TINYUSB.
No longer needed as shared tinyusb is now used by the esp32 port.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-07 11:06:57 +11:00
Andrew Leech
4247921c4e esp32: Use shared/tinyusb integration for S2 and S3 USB.
Uses newer TinyUSB synopsys/dwc2 driver for esp32s2 and esp32s3 rather than
the IDF tinyusb component.  This allows re-use of other tinyusb integration
code and features shared between ports.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-10-07 11:06:29 +11:00
Damien George
ca6723b144 rp2/cyw43_configport: Define CYW43_PRINTF to mp_printf to get messages.
The cyw43-driver uses `printf` by default for `CYW43_PRINTF`, but on the
rp2 port `printf` only goes to a UART output and not to USB CDC.

By defining `CYW43_PRINTF` to `mp_printf`, all the messages from the
cyw43-driver are seen on USB CDC.

For example this allows `network.WLAN().config(trace=1)` to show async
WALN events.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-03 12:12:18 +10:00
Alessandro Gatti
ca220b5fc5 py/nlrrv64: Add RISC-V RV64I NLR implementation.
Add custom NLR support for 64 bits RISC-V RV64I targets.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-10-03 12:06:19 +10:00
Alessandro Gatti
e39bd3ae9d shared/runtime/gchelper_rv64i: Fix opcode sw/sd typo.
The version of the assembly code for the GC helper that was committed
ended up being a version that had an opcode typo in.

The code was tested and working, but an undo operation too many when
cleaning up the file before committing checked in the wrong version.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-10-03 11:40:10 +10:00
Damien George
70a01550c9 unix/alloc: Remove unused MICROPY_FORCE_PLAT_ALLOC_EXEC option.
The `MICROPY_FORCE_PLAT_ALLOC_EXEC` config option was made obsolete by
commit 9796625457, so remove it.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-03 11:09:42 +10:00
Damien George
1291718916 github/workflows: Free up disk space on zephyr workflow.
The zephyr builds take up quite a lot of space.

Signed-off-by: Damien George <damien@micropython.org>
2024-10-03 10:36:27 +10:00
Maureen Helm
a9803f4711 zephyr: Allow using devicetree node labels to construct machine objects.
Zephyr v3.7.0 added a new feature to allow getting devices by their
devicetree node labels. Use this feature in the MicroPython Zephyr port
to simplify constructing machine module objects, including Pin, SPI,
I2C, and UART. It's still possible to use the more verbose device names
(e.g., gpio@400ff040, i2c@40066000, spi@4002c000), but now we can also
use their devicetree node labels (e.g., gpiob, i2c0, spi0).

Node labels aren't standardized across all SoC families because they
generally try to follow their respective SoC hardware user manual naming
convention, however many boards define common labels for devices routed
to Arduino headers (e.g., arduino_i2c, arduino_serial, and arduino_spi).
That means I2C("arduino_i2c") will work on quite a few boards (>100 in
the main Zephyr tree).

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2024-10-01 20:02:01 -05:00
Maureen Helm
f33df7197e zephyr: Refactor device lookup into a common helper function.
Refactors Zephyr device lookup operations into a common helper function
to reduce boilerplate code that was repeated in multiple modules.

Suggested-by: Damien George <damien@micropython.org>
Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2024-10-01 20:02:01 -05:00
Maureen Helm
545d4efb55 zephyr: Upgrade to Zephyr v3.7.0.
Updates the Zephyr port build instructions and CI to use the latest
Zephyr release tag.

Tested on frdm_k64f.

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2024-10-02 07:49:53 +10:00
Maureen Helm
fa7b4c48bc tools/ci.sh: Upgrade Zephyr docker image 0.26.13 and SDK 0.16.8.
Upgrades CI to use the latest versions of the Zephyr docker image and
Zephyr SDK.

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2024-10-02 07:49:53 +10:00
Maureen Helm
e191265f7f zephyr: Change SPI chip select from a pointer to a struct member.
Zephyr v3.4.0 changed the SPI chip select from a pointer to a struct
member to allow using the existing SPI dt-spec macros in C++.

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2024-10-02 07:49:53 +10:00
Maureen Helm
a7ae3a385e zephyr: Change main function to return an int.
Zephyr v3.4.0 changed the declaration of the main function to return an
int to allow building Zephyr without the -ffreestanding compiler flag.

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2024-10-02 07:49:53 +10:00
Maureen Helm
90c5b04a97 zephyr: Replace deprecated FLASH_AREA macros with FIXED_PARTITION.
Zephyr v3.2.0 deprecated FLASH_AREA macros in favor of FIXED_PARTITION
macros, using node labels instead of node label properties to reference
flash storage partitions.

Signed-off-by: Maureen Helm <maureen.helm@intel.com>
2024-10-02 07:49:53 +10:00
Maureen Helm
2407c46dac docs/zephyr: Update docs to reflect device name changes.
Zephyr v3.2.0 deprecated the devicetree label property as a base
property, which had been used as the device name string for
device_get_binding(). The device name string is now the devicetree node
name appended with its unit-address. Update Zephyr port documentation
to reflect this change.

Signed-off-by: Maureen Helm <maureen.helm@intel.com>
2024-10-02 07:49:30 +10:00
Maureen Helm
4e59a51902 zephyr: Replace zephyr.h with kernel.h.
Zephyr v3.2.0 deprecated include/zephyr/zephyr.h in favor of
include/zephyr/kernel.h since it only included that header.

Signed-off-by: Maureen Helm <maureen.helm@intel.com>
2024-10-02 00:07:46 +10:00
Maureen Helm
3a3dbf524b zephyr: Update include paths to use the zephyr namespace.
Zephyr v3.1.0 moved all public headers to include/zephyr. Updates a few
Zephyr include paths that were missed in
4fd54a4756.

Signed-off-by: Maureen Helm <maureen.helm@intel.com>
2024-10-02 00:07:46 +10:00
Alessandro Gatti
17d8234458 py/parse: Remove old esp32 compiler workaround.
The ESP32 port contains a workaround to avoid having a certain function
in `py/parse.c` being generated incorrectly.  The compiler in question
is not part of any currently supported version of ESP-IDF anymore, and the
problem inside the compiler (well, assembler in this case) has been
corrected a few years ago.

This commit removes all traces of that workaround from the source tree.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-27 00:03:16 +10:00
Angus Gratton
73feaaf931 rp2/machine_uart: Fix dropped UART REPL bytes on soft reset.
Necessary to fix "mpremote run" over hardware UART.

Bisect shows bug was introduced by d420b4e4, but looks like made more
complex by 01c046d2. Specifically: resetting and re-initialising the REPL
UART during soft reset clears the FIFO before it's done printing the "MPY:
soft reboot" line.

Fixed by adding a UART TX flush in the deinit path.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-26 23:43:11 +10:00
Alessandro Gatti
43b05afdf5 py/mpz: Skip separators when running out of digits to print.
This commit fixes the addition of a stray separator before the number
when printing an MPZ-backed integer and the first group is three digits
long.

This fixes #8984.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-26 23:39:06 +10:00
Damien George
b0ba151102 shared/tinyusb: Use new persistent-tx-fifo configure interface.
The old configuration option has been removed from TinyUSB.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-26 23:13:50 +10:00
Damien George
09fa90ed47 lib/tinyusb: Update to version 0.17.0.
Includes support for RP2350, and improvements for ESP32.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-26 23:13:34 +10:00
Damien George
40048f0f25 ports: Fix lwIP config setting to disable DHCP ARP check.
lwIP was recently updated in a89ac9e24a
to STABLE-2_2_0_RELEASE, and this introduced a change in the configuration
variable `DHCP_DOES_ARP_CHECK`, renaming it to `LWIP_DHCP_DOES_ACD_CHECK`.

This commit fixes the ports lwIP settings to use the new configuration
option.

Without this option, connecting to a WiFi access-point takes about 12.5
seconds.  With this option (ie disabling DHCP ARP checks) connecting takes
about 4 seconds.

Tested on an RPI_PICO_W and PYBD_SF2.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-26 23:00:42 +10:00
Damien George
36fe9bbf00 unix/alloc: Don't trace executable memory for GC pointers.
This tracing was originally needed for three reasons:

1. To trace object/raw-code pointers embedded in native code, eg from
   @micropython.native functions.

2. To trace pointers to BSS/rodata from relocated viper code.

3. For libffi tracing.

The tracing in point 1 was made unnecessary long ago in commit
7d4b6cc868 (see also commit
bbccb0f630 which removed scanning of native
code on the esp8266 port).

Since the previous commit, point 2 is no longer needed.

For point 3, this was made unnecessary in the recent commit
9796625457.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-26 22:36:55 +10:00
Damien George
5b22bde044 py/persistentcode: Explicitly track native BSS/rodata when needed.
Signed-off-by: Damien George <damien@micropython.org>
2024-09-26 22:15:28 +10:00
Angus Gratton
f4ab9d9247 extmod/vfs_blockdev: Implement common helper for read and write.
- Code size saving as all of these functions are very similar.
- Resolves the "TODO" of the plain read and write functions not propagating
  errors. An error in the underlying block device now causes VFatFs to
  return EIO, for example.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-26 22:08:48 +10:00
Angus Gratton
4f6d4b2b49 extmod/vfs_blockdev: Check block device function positive results.
A positive result here can result in eventual memory corruption
as littlefs expects the result of a cache read/write function to be
0 or a negative integer for an error.

Closes #13046

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-26 22:08:48 +10:00
Andrew Leech
a2475ee9de renesas-ra/usb: Use interrupt rather than polling for USB task.
Most ports using TinyUSB now schedule the USB tasks from the USB interrupt.
This commit updates the renesas-ra port to use this new pattern.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-09-26 17:45:16 +10:00
Takeo Takahashi
6381ad5d0c renesas-ra/extint: Fix issue with Pin.irq not triggering.
Fixes issue #15272.

Signed-off-by: Takeo Takahashi <takeo.takahashi.xv@renesas.com>
2024-09-26 17:40:30 +10:00
Takeo Takahashi
57f76f4c62 renesas-ra/boards: Add configuration.xml for auto-generated files.
* configuration.xml: Generated by RA Smart Configurator for FSP 4.4.

Signed-off-by: Takeo Takahashi <takeo.takahashi.xv@renesas.com>
2024-09-26 17:36:34 +10:00
Andrew Leech
188ca7d08a renesas-ra/README: Add basic details about board autogen files.
The renesas-ra port board definitions contain auto-generated files which
are not easy to understand for someone unfamiliar with the port.  This
commit adds some notes to the README to assist other developers who want to
work on these.

The configuration.xml file for the `ARDUINO_PORTENTA_C33` was provided by
@iabdalkader.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-09-26 17:27:42 +10:00
iabdalkader
51974f20e1 stm32/boards/ARDUINO_GIGA: Update board config files.
To remove duplicate HAL macros.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-24 12:56:59 +10:00
iabdalkader
e5984fb6da stm32/boards/ARDUINO_NICLA_VISION: Update board config files.
Changes are:
- Add pre/post stop mode entry macros.
- Make SE05X pin accessible.
- Remove duplicate HAL macros.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-24 12:56:53 +10:00
iabdalkader
a4e3830d39 stm32/boards/ARDUINO_PORTENTA_H7: Update board config files.
Changes are:
- Add pre/post stop mode entry macros.
- Make SE05X pin accessible.
- Remove duplicate HAL macros.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-24 12:56:42 +10:00
iabdalkader
fc006a0412 stm32/boards/ARDUINO_OPTA: Add support for the Arduino Opta board.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-24 12:56:21 +10:00
iabdalkader
3a2252b4c2 stm32/powerctrl: Add pre/post stop mode entry macros.
These allow a board to perform actions before/after stop mode.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-24 12:55:54 +10:00
iabdalkader
eec5eb4260 stm32/uart: Add UART RX/CTS pin pull config options.
The UART driver enables a pull-up on RX/CTS pins by default.  This can
cause UART to fail to receive in certain situations, eg with RS485
transceivers.

This commit adds compile-time configuration options to set the pull mode on
the RX and CTS pins of each UART.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-24 10:20:29 +10:00
Alessandro Gatti
3e085c3aa6 tools/ci.sh: Report code size for VIRT_RV32 as well.
This commit adds the `VIRT_RV32` board to the list of targets for
calculating code size changes as part of the CI pipeline.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 13:03:26 +10:00
Alessandro Gatti
58e7689142 tools/metrics.py: Add VIRT_RV32 to the code size metrics.
This commit adds the Qemu-based RISC-V 32 bits `VIRT_RV32` board to the
list of ports/boards to be built for measuring code size changes.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 13:03:26 +10:00
Alessandro Gatti
8a9042a72b github/workflows: Update Ubuntu images for code size CI tasks.
This updates the Ubuntu OS image the code size CI tasks run on, from
20.04-LTS to 22.04-LTS.  This is needed because 20.04 didn't have
packages that are needed to build RISC-V 32 code.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 12:42:07 +10:00
Alessandro Gatti
f1b88e0d59 gitignore: Add ffi_lib.so to the gitignore list.
When testing the Unix port with FFI tests enabled, the FFI helper
library that's built as part of the testing process is not removed after
the tests session end.

This commit adds the built library to the gitignore list, so it doesn't
mark the sourcetree as dirty if a test run for the Unix port was started
in the past.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 11:47:18 +10:00
Alessandro Gatti
8f465dfd10 unix/modffi: Restrict uint32_t values to 32 bits.
This commit clears the upper 32 bits of returned `uint32_t` values,
which are handled as `unsigned int`s by the MicroPython runtime and
thus could be extended to 64 bits on some platforms.

RV64 holds 32-bit values as signed integers when held in registers, but
the code handling the FFI unsigned int case did not take this into
account.  That introduced test failures when a 32-bit value had its most
significant bit set, as when performing the value extension from 32 to
64 bits, the upper half of the value would be filled with ones.

On 32 bit platforms this change should be converted to a no-op, and
on other 64 bit platforms that aren't RISC-V it shouldn't hurt as the
value being manipulated is expected to only hold valid bits in its lower
half.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 11:47:18 +10:00
Alessandro Gatti
bb3c711c04 tools/ci.sh: Let RV64 use a source-built version of libffi.
This commit lets the RV64 port use the version of libffi that is bundled
as a submodule in the MicroPython source tree, as the packaged libffi
library coming from Ubuntu's RISC-V repository trashes foreign function
call results on exit.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 11:47:18 +10:00
Alessandro Gatti
9796625457 unix/modffi: Clean up FFI closures memory management.
This commit removes custom FFI closures alloc/free functions, in favour
of using the tracked allocation facility to allocate memory for FFI
callback objects.

This stems from linking issues in the Arm port when updating LibFFI to
the latest stable version, as the overridden alloc/free functions didn't
replace LibFFI's (unlike in other ports).  The original code did no
effective cleanup for allocated callback objects, so there is no real
impact when switching allocation strategy.

The tracked allocation feature used to be enabled only if the Bluetooth
stack integration was enabled.  This commit also enables tracked
allocation support if FFI support is enabled.

Co-authored-by: Damien George <damien@micropython.org>
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 11:47:18 +10:00
Alessandro Gatti
2b5feb9121 lib/libffi: Update libffi to 3.4.6.
Libffi is updated to the latest stable version (v3.4.6) as the version
of libffi that was linked by the repository predates the introduction of
RISC-V processors (both 32 and 64 bits).

This is necessary as the packaged version of libffi used by the CI for
RISC-V 64 turned out to simply not work correctly, whilst a source-built
version of libffi worked just fine.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-23 11:47:18 +10:00
Seon Rozenblum
b08ddbba59 esp32/boards/UM_RGBTOUCH_MINI: Fix compile error with missing modules.
Signed-off-by: Seon Rozenblum <seon@unexpectedmaker.com>
2024-09-20 15:57:52 +10:00
Andrew Leech
7e14680a83 py/objringio: Add micropython.RingIO() interface for general use.
This commit adds a new `RingIO` type which exposes the internal ring-buffer
code for general use in Python programs.  It has the stream interface
making it similar to `StringIO` and `BytesIO`, except `RingIO` has a fixed
buffer size and is automatically safe when reads and writes are in
different threads or an IRQ.

This new type is enabled at the "extra features" ROM level.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2024-09-19 18:00:44 +10:00
shiggy
6c73573b34 esp32/boards/OLIMEX_ESP32_EVB: Add Olimex ESP32 EVB board definition.
This is for boards not covered by the Olimex ESP32 PoE implementation.  The
major setting is about the PHY interface configuration.

Tested with esp-idf v5.0.4 and Olimex ESP32 EVB boards.

Signed-off-by: shiggy <mail@shiggytech.de>
2024-09-19 15:56:27 +10:00
Seon Rozenblum
9b5f99eb59 esp32/boards: Add UM_OMGS3 and UM_RGBTOUCH_MINI board definitions.
This adds two new UM boards: OMGS3 and RGB Touch Mini.  Also fixed the
NanoS3 deploy info.

Signed-off-by: Seon Rozenblum <seon@unexpectedmaker.com>
2024-09-19 15:13:35 +10:00
Seon Rozenblum
d775db72b9 esp32/boards/UM_FEATHERS3NEO: Add FeatherS3 Neo board definition.
Signed-off-by: Seon Rozenblum <seon@unexpectedmaker.com>
2024-09-19 15:06:04 +10:00
Michael Sawyer
230e521515 tests/ports/unix: Update and extend the modffi integer tests.
Added the "long" modffi tests. The tests could not be added to the existing
ffi_types test because two .exp files were required for the 32-bit and
64-bit results. Code common to both the ffi_types and type "long" tests was
factored into ffi_int_base. ffi_types was renamed to ffi_int_types to group
the related tests under the "ffi_int" prefix.

Signed-off-by: Michael Sawyer <mjfsawyer@gmail.com>
2024-09-19 15:00:17 +10:00
Michael Sawyer
b05983ff6d unix/modffi: Fix signed integer cast in return_ffi_value.
Casting an ffi_arg to a signed int may truncate the value. E.g., when the
ffi_arg is 64-bit and the signed int is 32-bit. Also, casting an ffi_arg
to a larger signed type will not sign extend the value. E.g., when the
ffi_arg is 32-bit and the larger signed type is int64_t. If the value is
signed, it should be cast to ffi_sarg, which is the same size as ffi_arg.

Signed-off-by: Michael Sawyer <mjfsawyer@gmail.com>
2024-09-19 15:00:06 +10:00
Damien George
8b35f2c7fa tools/mpy_ld.py: Support jumping more than 2k on armv6m architectures.
Native .mpy files targetting armv6m (eg RP2040) cannot currently have more
than about 2kiB of native code (between the start of the file and the init
function).

This commit fixes that by using bigger jumps to jump to the init function.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-19 14:52:58 +10:00
Alessandro Gatti
46d8db81d3 tools/ci.sh: Clean up the Unix port's Arm target.
The Unix port's Arm target CI steps have been updated to be more in
line with the other targets (the MicroPython binary doesn't need an
environment variable to be set in order to run now).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-19 13:49:12 +10:00
Alessandro Gatti
52d5f39881 tools/ci.sh: Add missing FFI helper for CI RV64 Unix builds.
The FFI helper definition was accidentally omitted when committing the
necessary shell code for building RV64 Unix builds in the CI
environment.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-19 13:49:12 +10:00
Alessandro Gatti
7b5738ad86 tools/ci.sh: Clean up the Unix port's MIPS target.
The Unix port's MIPS target CI steps have been updated to be more in
line with the other targets (the MicroPython binary now runs as a
dynamic executable), and the test exceptions for ffi have been lifted.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-19 13:49:12 +10:00
Damien George
1be38e8077 tests/run-tests.py: Remove --write-exp and --list-tests options.
Removing the now-unused (see previous commit for details) `--write-exp` and
`--list-tests` options helps to simplify the rather complex logic in
`run-tests.py`.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-19 13:36:04 +10:00
Damien George
067ef81cd0 all: Remove tinytest component.
With the recent qemu (d9a0fdda9a and
0426934969) and zephyr
(05cad7b56f) changes to how their tests are
run, two things became unused:

- The tinytest framework, which embedded a set of tests and their expected
  output within firmware, so these tests could be run stand-alone.

- The `--write-exp` and `--list-tests` options to `tests/run-tests.py`,
  which were needed primarily to generated the expected test output for
  tinytest (also the associated `tests/run-tests-exp.py/.sh` scripts are
  now unused).

This commit removes the tinytest component and all its helper code.  This
eliminates a maintenance burden.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-19 13:31:36 +10:00
Angus Gratton
5d8878b582 shared/tinyusb: Only run TinyUSB on the main thread if GIL is disabled.
If GIL is disabled then there's threat of a race condition if some other
code specifically requests USB processing (i.e. to unblock stdio), while
a scheduled TinyUSB callback is already running on another thread.

Relies on the change in the parent commit, where scheduler is restricted
to main thread if GIL is disabled.

Fixes #15390 - "TinyUSB callback can't recurse" exceptions on rp2 when
using _thread module and USB serial I/O.

Adds a unit test for stdin functioning correctly in threads (fails on rp2
port without this fix).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-19 13:17:01 +10:00
Angus Gratton
52a593cdb1 py/scheduler: Only run callbacks on the main thread if GIL is disabled.
Otherwise it's very difficult to reason about thread safety in a
scheduler callback, as it can run at any time on any thread - including
racing against any bytecode operation on any thread.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-19 13:17:01 +10:00
iabdalkader
451ba1cf38 rp2/modules: Fix FatFS boot script to detect invalid FAT filesystem.
This change helps detect if the filesystem is invalid, by also including
the first mount attempt within the try-except.  Then the FAT is reformatted
if needed.

Fixes issue #15779.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-19 13:04:48 +10:00
ZodiusInfuser
ded8bbdd5e rp2/machine_pin_cyw43: Include check for CYW43_GPIO.
The `#if` check only checks that `MICROPY_PY_NETWORK_CYW43` and
`MICROPY_HW_PIN_EXT_COUNT` are defined.  This is a reasonable assumption
for the Pico W, but causes conflicts if someone wants to attach an external
IO expander to their Pico W and have its pins appear as Pin objects.

This commit addresses this by adding the additional checks, letting board
builds include wireless but separately choose whether the external IO pins
come from the cyw43 or not.

Signed-off-by: Christopher Parrott <chris@pimoroni.com>
2024-09-19 12:58:43 +10:00
ZodiusInfuser
79ba6d8ce7 rp2: Increase ext pins from 10 to 32.
To allow more pins when other ways are used to provide external GPIO (ie
not via cyw43).

Signed-off-by: Christopher Parrott <chris@pimoroni.com>
2024-09-19 12:54:20 +10:00
ZodiusInfuser
5dfd3ecd8b rp2: Add board-level hooks to main, and MICROPY_SOURCE_BOARD cmake var.
Signed-off-by: Christopher Parrott <chris@pimoroni.com>
2024-09-19 12:54:20 +10:00
Angus Gratton
fb069f9d06 docs/library: Document machine.Pin.toggle() method.
Original commit was by @millosolomillo from 2022, but CI no longer accepts
their auto-generated GitHub commit email...

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-19 12:04:39 +10:00
Damien George
8feb714b4d docs/library: Document math.log with two arguments.
The functionality is there but was not documented.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-17 11:22:26 +10:00
Damien George
3d53b39a2a docs/reference: Fix pyboard.py filesystem cp example with three files.
Fix documentation to match behaviour (directories are not preserved).

Fixes issue #11101.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-17 11:20:17 +10:00
Paul Grayson
0d8388673e docs/esp32: Update pin access example with addresses for ESP32-S3.
Signed-off-by: Paul Grayson <pdg@alum.mit.edu>
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-17 11:18:47 +10:00
Matt Trentini
7953089a25 examples/natmod: Fix URL links in README.md.
Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-09-17 11:14:52 +10:00
Matt Trentini
976d9d148f stm32/boards/STM32F429DISC: Add DAC support to the STM32F429DISC.
The STM32F429DISC board definition did not have DAC enabled, however the
micro/board supports it so this commit enables the feature.

Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-09-17 10:58:47 +10:00
Adrian Higgins
39ddfed9a0 stm32: Update STM32L452xx Multi OTG handling.
Added custom Multi OTG handling for STM32L452xx, based on STM32L432xx
handling.

Fixes issue #15795.

Signed-off-by: Adrian Higgins <adrian@higstar.com>
2024-09-17 10:56:23 +10:00
Amirreza Hamzavi
f1bdac3752 unix/README: Fix typo in build dependencies.
Signed-off-by: Amirreza Hamzavi <amirrezahamzavi2000@gmail.com>
2024-09-10 11:30:22 +10:00
danicampora
3ca01eccae zephyr/mphalport: Make mp_hal_wait_sem() always call k_poll().
Also even in the case of a zero timeout given.

Signed-off-by: danicampora <danicampora@gmail.com>
2024-09-06 20:48:13 +10:00
danicampora
1c0dc2ac3e zephyr/src: Remove k_yield() at the end of console_irq_input_hook().
Some boards like the nrf52840dk crash immediatelly after boot when
k_yield() is executed in this function.  It also makes the REPL randomly
lock up on other boards like the nucleo_wb55rg.

Signed-off-by: danicampora <danicampora@gmail.com>
2024-09-06 20:48:05 +10:00
Damien George
74d6dba294 tests/run-tests.py: Add a zephyr test target.
So that certain tests can be skipped when running on this target.  These
thread tests do not pass because the zephyr port cannot create more than 4
threads at once.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-06 20:47:19 +10:00
Damien George
0afec3974c zephyr/Kconfig: Increase default GC heap size to 48k.
So that more tests can run successfully, and so users by default have more
heap for applications.  Thin minimal configuration still has a 16k GC heap.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-06 20:42:57 +10:00
danicampora
935fcd1329 tests/thread: Adapt stress_aes.py to run on zephyr.
Signed-off-by: danicampora <danicampora@gmail.com>
2024-09-06 20:42:57 +10:00
Damien George
e7974a28f7 zephyr/mpconfigport: Enable mpz big integers.
These are needed to be on par with other ports.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-06 20:42:56 +10:00
Damien George
fc630e70c4 zephyr/main: Collect registers during a MicroPython GC scan.
Signed-off-by: Damien George <damien@micropython.org>
2024-09-06 20:42:56 +10:00
danicampora
7009c75f23 zephyr: Enable some core features to get more thread tests passing.
All these features are enabled at the
`MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES` level, and are required to get
more of the thread tests passing.

Signed-off-by: danicampora <danicampora@gmail.com>
2024-09-06 20:42:56 +10:00
danicampora
d68d8fcf90 zephyr: Re-implement the Zephyr console in non-blocking mode.
The standard Zephyr console implementation doesn't make use of
`tty_set_rx_timeout()` and therefore all the functions to receive
characters block indefinitely until data is received (including
`console_read()`).

This commit also releases the GIL where it applies, e.g. the REPL and the
time sleep functions.

Signed-off-by: danicampora <danicampora@gmail.com>
2024-09-06 20:42:56 +10:00
danicampora
6833f3dda9 zephyr: Add threading support.
This commit implements the `_thread` module on the zephyr port.

Due to the fact that we are still using a rather old version of Zephyr,
`CONFIG_DYNAMIC_THREAD` is not available and therefore the stack for
threads cannot be allocated dynamically, only at compile time.  So for the
time being and for the purpose of this commit, a maximum of 4 Zephyr
threads (besides the main thread) can be created.  Once we manage to update
to the latest version of Zephyr this won't be a problem anymore.

Configuration for the nrf52840dk is added as part of this change, because
this board was used to test the threading support.

The Zephyr option `CONFIG_THREAD_CUSTOM_DATA` is used to enable threading
on a per board basis.  The `thread.conf` file is added as a convenient way
to enable threading.

Signed-off-by: danicampora <danicampora@gmail.com>
2024-09-06 20:42:56 +10:00
Alexandre Iooss
aefd48b801 samd/Makefile: Specify UF2 family in firmware.uf2.
Set the UF2 firmware images family to Microchip SAMD21 or SAMD51.  This
helps tools such as file to identify built firmware.

Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
2024-09-06 20:36:06 +10:00
robert-hh
e23fdb1f77 tests/extmod/machine_uart_irq_txidle.py: Simplify the test script.
Now that no minimal delay time is required for SAMD devices.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-09-06 17:43:49 +10:00
robert-hh
1a6279ba37 samd/mphalport: Simplify mp_hal_delay_ms().
Do NOT use `mp_hal_delay_us()` for short delays.  This was initially done
to make short delays precise, but it does not allow for scheduling.  Leave
using `mp_hal_delay_us()` to user code if needed.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-09-06 17:43:49 +10:00
robert-hh
ed86fdbdf6 samd/mphalport: Fix an execution order bug in mp_hal_ticks_us_64().
The upper 32 bit of the 64 bit ticks register was taken before disabling
the interrupts.  That may have caused a wrong return values.  Besides that,
the function may cause trouble when called in an IRQ context, because it
unconditionally enables IRQ.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-09-06 17:16:44 +10:00
iabdalkader
3294606e23 extmod/libmetal: Fix libmetal rules for mkdir dependencies.
Dependency on auto-generated libmetal should be an order only prerequisite.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-09-06 17:14:03 +10:00
cajt
65244d291a extmod/modlwip: Fix compile error for lwIP with SLIP support.
Fixes a compile error if STM32 port is compiled with:

    make BOARD=(..) MICROPY_PY_LWIP=1 MICROPY_PY_LWIP_SLIP=1

`sio_send()` and `sio_tryread()` now use `mp_get_stream`.

Signed-off-by: Carl Treudler <cjt@users.sf.net>
2024-09-06 17:11:47 +10:00
Alessandro Gatti
a831c788f7 tools/mpy_ld.py: Ignore R_XTENSA_ASM_EXPAND relocation entries.
As reported in #14430 the Xtensa compiler can add R_XTENSA_ASM_EXPAND
relocation relaxation entries in object files, and they were not
supported by mpy_ld.

This commit adds handling for that entry, doing nothing with it, as it
is only of real use for an optimising linker.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-09-06 17:10:07 +10:00
Angus Gratton
e370999e37 unix: Add a description of COPT in the README.
This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-06 17:07:48 +10:00
Angus Gratton
d04974d8d0 unix: Expand the build steps in the README.
- Present the default build dependencies in one place at the top, and make
  a separate section about building standalone.

- Add steps for the "minimal" variant as well.

- Document that building standalone requires autoconf and libtool.

- Allow MICROPY_STANDALONE to be set as an environment variable.

Fixes issue #11313.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-06 17:07:35 +10:00
timdechant
455415b1e1 shared/runtime/sys_stdio_mphal: Fix printed type for stdio streams.
The printed type for stdio streams indicates "FileIO", which is a binary IO
stream.  Stdio is not binary by design, and its printed type should
indicate a text stream.  "TextIOWrapper" suits that purpose, and is used
by VfsPosix files.

Signed-off-by: timdechant <timdechant.git@gmail.com>
2024-09-06 17:00:35 +10:00
Damien George
659113825d qemu: Rename qemu-arm port to qemu.
Because this port now supports multiple architectures.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-06 11:08:39 +10:00
Damien George
3ea1ce63da all: Remove remaining qemu-riscv references.
Signed-off-by: Damien George <damien@micropython.org>
2024-09-06 11:08:22 +10:00
Damien George
0426934969 qemu-arm: Merge RISC-V 32-bit support into qemu-arm port.
Currently both the qemu-arm and qemu-riscv ports share a lot of code and
functionality.  This commit merges the qemu-riscv port into the qemu-arm
port.  The only real differences between the two are the toolchains used to
build the code, and the initialisation/startup framework.  Everything else
is pretty much the same, so this brings the following benefits:
- less code duplication
- less burden on maintenance
- generalised qemu port, could in the future support other architectures

A new board `VIRT_RV32` has been added to the qemu-arm port which is the
existing RISC-V board from the qemu-riscv port.  To build it:

    $ make BOARD=VIRT_RV32 repl

To cleanly separate the code for the different architectures, startup code
has been moved to ports/qemu-arm/mcu/<arch>/.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-04 16:46:39 +10:00
Damien George
f769b4329b qemu-arm/Makefile: Clean up SRC and OBJ variables.
Signed-off-by: Damien George <damien@micropython.org>
2024-09-04 16:46:39 +10:00
Damien George
dc9ecd5860 qemu-arm: Factor board config to mk fragments.
Signed-off-by: Damien George <damien@micropython.org>
2024-09-04 16:46:39 +10:00
Damien George
9396572eee tools/mpy-tool.py: Support freezing rv32imc native code.
Signed-off-by: Damien George <damien@micropython.org>
2024-09-04 16:46:39 +10:00
Damien George
6be1dbc784 tests/run-tests.py: Automatically detect native arch and mpy-cross flag.
Now that some ports support multiple architectures (eg esp32 has both
Xtensa and RISC-V CPUs) it's no longer possible to set mpy-cross flags
based on the target, eg `./run-tests.py --target esp32`.  Instead this
commit makes it so the `-march=xxx` argument to mpy-cross is detected
automatically via evaluation of `sys.implementation._mpy`.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-04 16:34:01 +10:00
Damien George
838c490eb4 tests/net_inet: Update micropython.org certificate for SSL tests.
The Let's Encrypt root certificate has changed so needs updating in this
test.

Signed-off-by: Damien George <damien@micropython.org>
2024-09-04 16:28:39 +10:00
Angus Gratton
fee9d66e3a esp32: Disable hardware stack protection on ESP32-C3.
Workaround for what appears to be an upstream issue:
https://github.com/espressif/esp-idf/issues/14456

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-04 15:15:26 +10:00
Angus Gratton
a6c35aeee8 esp32: Fix ARDUINO_NANO_ESP32 build configuration.
Regression introduced by 5e692d04 now at MICROPY_HW_USB_CDC is set.

The ARDUINO_NANO_ESP32 specifically builds shared/tinyusb/mp_usb_cdc.c
for the 1200bps reset behaviour. However MicroPython esp32 doesn't yet
use the rest of the shared/tinyusb functionality.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-04 11:06:21 +10:00
Angus Gratton
5e692d0460 esp32: Add MICROPY_HW_USB_CDC macro for native USB-CDC serial.
This fixes issue of ESP32-S3 switching its config over to USB serial/JTAG
instead of native USB.

The the existing logic was hard to follow, adding this config macro makes
it easier to see which USB is in use and to have board definitions that
enable/disable different USB levels.

This commit also drops (nominal) support for manually setting
CONFIG_ESP_CONSOLE_USB_CDC in sdkconfig. No included board configs use this
and it didn't seem to work (if secondary console was set to the default USB
Serial/JTAG then there is no serial output on any port, and if secondary
console was set to None then linking fails.) Can be re-added if there's a
use case for it.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-03 14:28:26 +10:00
Angus Gratton
6ad6297ef7 esp32: Fix ESP32-C3 USB serial/jtag peripheral pre-IDF 5.1.
Regression in 0a11832cd in IDF 5.0.x where macro
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED is not defined.

With this patch, ESP32-S3 still USB Serial/JTAG incorrectly (now on all
ESP-IDF versions).

Closes #15701

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-03 10:27:28 +10:00
Amirreza Hamzavi
1897fe6227 tests/basics: Add tests for optional args to int.to_bytes/from_bytes.
Signed-off-by: Amirreza Hamzavi <amirrezahamzavi2000@gmail.com>
2024-09-02 14:15:49 +10:00
Amirreza Hamzavi
cb7e99098e py/objint: Make byteorder argument optional in int.from_bytes() method.
This was made optional in CPython 3.11.

Signed-off-by: Amirreza Hamzavi <amirrezahamzavi2000@gmail.com>
2024-09-02 14:15:45 +10:00
Amirreza Hamzavi
0b432b3306 py/objint: Make length argument optional in int.to_bytes() method.
This was made optional in CPython 3.11.

Signed-off-by: Amirreza Hamzavi <amirrezahamzavi2000@gmail.com>
2024-09-02 14:14:36 +10:00
Amirreza Hamzavi
80c5e76483 py/objint: Make byteorder argument optional in int.to_bytes() method.
This was made optional in CPython 3.11.

Signed-off-by: Amirreza Hamzavi <amirrezahamzavi2000@gmail.com>
2024-09-02 14:14:22 +10:00
Andrew Leech
9670666623 stm32/boards: Enable RAM_ISR feature on boards with UART REPL.
Allows mpremote file transfer to work correctly when mpremote is used over
the ST-link USB/UART REPL port.

Fixes issue #8386.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2024-09-02 11:30:40 +10:00
Andrew Leech
1f5cab9edb stm32: Add option to put ISR, flash and UART code in RAM.
This allows UART RX to function while flash erase/writes operations are
under way, preventing lost serial data so long as it fits in the UART RX
buffer.

This enables (among other things) mpremote to successfully copy files to
boards that use a UART REPL.

Enable via the following option placed in `mpconfigboard.mk`:

    MICROPY_HW_ENABLE_ISR_UART_FLASH_FUNCS_IN_RAM = 1

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2024-09-02 11:30:34 +10:00
Damien George
35b6a66b0b docs/library: Document the network.PPP class.
Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:47:55 +10:00
Damien George
851aa06461 rp2: Integrate optional network.PPP.
Can be enabled by a board by enabling `MICROPY_PY_NETWORK_PPP_LWIP`.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:47:55 +10:00
Damien George
aee002dd80 stm32/lwip_inc: Implement LWIP_PLATFORM_DIAG macro in terms of printf.
This allows enabling lwIP debugging output.  For example, to enable PPP
debugging add the following to `mpconfigboard.h`:

    #define LWIP_DEBUG 1
    #define PPP_DEBUG LWIP_DBG_ON

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:47:55 +10:00
Damien George
a1a16ffd75 stm32/uart: Use timeout_char even with CTS enabled.
When timeout=0 (non-blocking mode) the UART should still wait for each
character to go out.  Otherwise non-blocking mode with CTS enabled is
useless because it can only write one character at a time.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:47:55 +10:00
Damien George
d8b033776e stm32/machine_uart: Return number of bytes written even with timeout.
The errcode should be cleared so the caller sees a successful write, even
if it's a short write.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:47:13 +10:00
Damien George
c94a3205b0 stm32/machine_uart: Allow changing only the baudrate.
Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:46:13 +10:00
Damien George
a5cc4d4623 stm32: Integrate optional network.PPP.
Can be enabled by a board by enabling `MICROPY_PY_NETWORK_PPP_LWIP`.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:46:13 +10:00
Damien George
bc952d37fe extmod/network_ppp_lwip: Add network.PPP via lwIP.
This commit adds a new `network.PPP` interface which works on any port that
has bare-metal lwIP, eg rp2, stm32, mimxrt.

It has been tested on stm32.  A board needs to enable
`MICROPY_PY_NETWORK_PPP_LWIP` and then it can use it as follows:

    import network

    ppp = network.PPP(uart)
    ppp.connect()

    while not ppp.isconnected():
        pass

    # use `socket` module as usual, etc

    ppp.disconnect()

Usually the application must first configure the cellular/etc UART link to
get it connected and in to PPP mode first (eg ATD*99#), before handing over
control to `network.PPP`.

The PPP interface automatically configures the UART IRQ callback to call
PPP.poll() on incoming data.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:46:13 +10:00
Damien George
664dd7b54a extmod: Update make and cmake scripts to work with latest lwIP.
Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:46:13 +10:00
Damien George
a89ac9e24a lib/lwip: Update lwIP to STABLE-2_2_0_RELEASE.
This updates lwIP from STABLE-2_1_3_RELEASE, which was released in November
2021.  The latest STABLE-2_2_0_RELEASE was released in September 2023.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 23:45:34 +10:00
Damien George
09d070aa55 tests/extmod_hardware: Add tests for machine.UART.IRQ_RX/RXIDLE/BREAK.
These all require hardware connections, so live in a different directory.

Except for the IRQ_BREAK test of ESP32 devices a single UART with loopback
is sufficient.

General:
    SAMD21: Due to the limited flash size only SAMD21 devices with external
    flash support uart.irq().

IRQ_BREAK:
    ESP32 needs different UART devices for creating and sensing a break.
    Lacking a second UART the test is skipped for ESP32S2 and ESP32C3.  RP2
    does not pass the test reliable at 115200 baud, reason to be found.
    Thus the upper limit is set to 57600 Baud.

    Coverage:
        esp32  pass when different UART devices are used.
        rp2    pass up to 57600 baud

IRQ_RX:
    SAMD21: Being a slow device it needs data to be sent byte-by-byte at
    9600 baud, since the IRQ callback is scheduled delayed and then the
    flags do not match any more.  The data matches since it is queued in
    the FIFO resp. ringbuffer.

    CC3200: The test cannot be performed since no calls are accepted in the
    IRQ handler like u.read(). Skipped.

    Coverage:
        cc3200 fail due to major differences in the implementation.
        esp32  pass
        nrf    pass
        renesas-ra pass
        samd   pass see the notes.
        stm32  pass

IRQ_RXIDLE:
    STM32: With PyBoard the IRQ is called several times, but only once with
    the flag IRQ_RXIDLE set.

    Coverage:
        esp32    pass
        mimxrt   pass
        renesas-ra pass
        rp2      pass
        samd     pass for both SAMD21 and SAMD51
        stm32    fail. see notes.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:48:09 +10:00
Damien George
b8513e6137 tests/extmod: Add test for machine.UART.IRQ_TXIDLE.
The test checks whether the message created by the IRQ handler appears
about at the end of the data sent by UART.

Supported MCUs resp. boards:
- RP2040
- Teensy 4.x
- Adafruit ItsyBitsy M0
- Adafruit ItsyBitsy M4
- NRF52 (Arduino Nano Connect 33 BLE)

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 16:48:09 +10:00
robert-hh
03b1b6d8e6 docs/library/machine.UART: Extend the documentation for UART.irq.
For more ports and trigger options, based on the current state of the code.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:48:09 +10:00
Damien George
9bbe61607a docs/library/machine.UART: Fix UART.irq docs to match current code.
These docs now match the code in `extmod/machine_uart.c`.  IRQ trigger
support still need to be updated for each port (to be done in a follow-up
commit).

Signed-off-by: Damien George <damien@micropython.org>
2024-08-29 16:34:45 +10:00
robert-hh
a38b4f4287 esp32/machine_uart: Implement UART.RX_IDLE based on machine.Timer.
The UART.IRQ_IDLE callback is called about two character times after the
last byte, or 1 ms, whichever is larger.  For the irq, timer 0 is used.

machine_timer.c had to be reworked to make it's mechanisms available for
machine_uart.c.

The irq.flags() value is change only at a requested event.  Otherwise keep
the state.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:34:33 +10:00
robert-hh
7045975d04 renesas-ra/machine_uart: Implement UART.IRQ_RXIDLE based on softtimer.
Allowing to define the trigger UART.IRQ_RXIDLE as well as UART.IRQ_RX.  The
delay for the IRQ_RXIDLE interrupt is about 3 character times or 1-2 ms,
whichever is larger.

The irq.flags() value is changed only with an expected event.  Do not
change it otherwise.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
ef69d0f2d3 samd/machine_uart: Implement UART.IRQ_RXIDLE based on the softtimer.
With the softtimer the minimal delay between the end of a message and the
trigger is 2 ms.  For baud rates <= 9600 baud it's three character times.
Tested with baud rates up tp 115200 baud.  The timer used for RXIDLE is
running only during UART receive, saving execution cycles when the timer is
not needed.

The irq.flags() value is changed only with an expected event.  Do not
change it otherwise.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
a86619fb6f stm32/machine_uart: Add the UART.IRQ_RX event for UART.irq().
Just adding the event symbol.  No code change required, and no impact on
code execution time when the event is not selected.

Tested with STM32F4xx, STM32F7xx and STM32H7xx.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
bae809070e nrf/modules/machine/uart: Implement Python UART IRQ for nrf52840 boards.
Supported triggers: UART.IRQ_RX and UART.IRQ_TXIDLE.  It will probably work
on other boards as well, but so far untested.

The irq.flags() value is changed only when requested by a triggered event.
Do not change it otherwise.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
4da5de94bb nrf/modules/machine/uart: Allow changing the UART baud rate w/o reset.
This commit fixes a bug in the existing driver, that the UART baud rate
could not be changed without reset or power cycle.  It adds as well
functionality to UART.deinit().

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
a04a14163b esp32/machine_uart: Implement Python UART IRQ with IRQ_RX and IRQ_BREAK.
Supported trigger events: IRQ_RX and IRQ_BREAK.  Hard IRQ is not supported.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
1027b5f083 cc3200/mods/pybuart: Add the UART.IRQ_RX class constant.
As alternative to RX_ANY to match the names used by the other ports.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
324c675347 renesas-ra/machine_uart: Add the UART.IRQ_RX class constant.
The renesas-ra port supports calling a handler to be called on every byte
received by UART.  For consistency with other ports, the symbol IRQ_RX
is added as the trigger name.

Side change: Add the received UART data to the REPL input buffer only if it
is the REPL UART.  Otherwise, every UART would act as REPL input.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
b7fa4e2fc8 mimxrt/machine_uart: Implement a Python UART IRQ handler.
Supported triggers are: IRQ_RXIDLE and IRQ_TXIDLE.

When IRQ_RXIDLE is set, the handler will be called 3 character times after
the data in burst stopped.

When IRQ_TXIDLE is set, the handler will be called immediately after the
data has been sent.

This commit requires a change to fsl_lpuart.c, because the existing code
does not support under-run appropriately.

The irq.flags() value is cleared only at an expected event.  Do not change
it otherwise.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
8e1123b25b samd/machine_uart: Implement a Python UART IRQ handler.
Supported for all SAMD51 devices and SAMD21 with external flash.  For
interrupt events, IRQ_RX and IRQ_TXIDLE are provided.

IRQ_RX is called for every received byte.  This may not be useful for high
data rates, but can be used to build a wrapper class providing an
IRQ_RXIDLE event or to signal just the first byte of a message.

IRQ_TXIDLE is called only when messages are longer than 5 bytes and
triggers when still 5 bytes are due to be sent.

The SAMD hardware does not support implementing IRQ_RXIDLE.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
robert-hh
01c046d2a8 rp2/machine_uart: Implement a Python UART IRQ handler.
Supported trigger names: IRQ_RXIDLE, IRQ_TXIDLE, IRQ_BREAK

- IRQ_RXIDLE: The handler for IRQ_RXIDLE is called reliably 31 UART bit
  times after the last incoming data.

- IRQ_TXIDLE: This IRQ is triggered after at least >5 characters are sent
  at once.  It is triggered when the TX FIFO falls below 4 elements.  At
  that time, up to 5 bytes may still be in the FIFO and output shift
  register.

- IRQ_BREAK: The IRQ triggers if a BREAK state is detected at RX.
  Properties & side effects:
  - After a BREAK, a valid character must be received before another break
    can be detected.
  - Each break puts a 0xff character into the input buffer.

The irq.flags() value is cleared only with a new wanted event.  Do not
change the flags otherwise.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-29 16:27:43 +10:00
Damien George
fd03a0587f examples/network: Support full URLs in HTTP(S) client examples.
Not just the domain name.  This gives better HTTP 1.0 examples if someone
wants to copy them.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 12:28:58 +10:00
Damien George
d75705311a examples/network: Use SSLContext instead of old ssl.wrap_socket.
`ssl.wrap_socket()` is deprecated in CPython, so use `SSLContext` instead,
so the example is a good example to copy.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 12:28:58 +10:00
Damien George
c8385ef75a examples/network: Support IPv4 and IPv6 in HTTP client examples.
The main changes here are to pass the address family and socket type to
`getaddrinfo()`, and then use the result of the address lookup when
creating the socket, so it has the correct address family.

This allows both IPv4 and IPv6 to work, because the socket is created with
the correct AF_INETx type for the address.

Also add some more comments to the examples to explain what's going on.

Fixes issue #15580.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 12:28:58 +10:00
Damien George
d9a0fdda9a qemu-arm: Rework to provide a REPL and run tests via a pty serial port.
Currently, the qemu-arm (and qemu-riscv) port has two build modes:
- a simple test that executes a Python string; and
- a full test that uses tinytest to embed all tests within the firmware,
  then executes that and captures the output.

This is very different to all the other ports.  A difficulty with using
tinytest is that with the large number of tests the firmware overflows its
virtual flash size.  It's also hard to run tests via .mpy files and with
the native emitter.  Being different to the other ports also means an extra
burden on maintenance.

This commit reworks the qemu-arm port so that it has a single build target
that creates a standard firmware which has a REPL.  When run under
qemu-system-arm, the REPL acts like any other bare-metal port, complete
with soft reset (use machine.reset() to turn it off and exit
qemu-system-arm).

This approach gives many benefits:
- allows playing with a REPL without hardware;
- allows running the test suite as it would on a bare-metal board, by
  making qemu-system-arm redirect the UART serial of the virtual device to
  a /dev/pts/xx file, and then running run-tests.py against that serial
  device;
- skipping tests is now done via the logic in `run-tests.py` and no longer
  needs multiple places to define which tests to skip
  (`tools/tinytest-codegen.py`, `ports/qemu-arm/tests_profile.txt` and also
  `tests/run-tests.py`);
- allows testing/using mpremote with the qemu-arm port.

Eventually the qemu-riscv port would have a similar change.

Prior to this commit the test results were:

    743 tests ok.  (121 skipped)

With this commit the test results are:

    753 tests performed (22673 individual testcases)
    753 tests passed
    138 tests skipped

More tests are skipped because more are included in the run. But overall
more tests pass.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:52:08 +10:00
Damien George
8a3842eba7 qemu-arm/uart: Implement uart_rx_chr.
Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:52:08 +10:00
Damien George
e8863e44e5 qemu-arm/Makefile: Make the build directory reflect the board.
So multiple boards can be built at once.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:52:08 +10:00
Damien George
1090f1a60c shared/runtime/semihosting_arm: Add mp_semihosting_exit.
Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:52:08 +10:00
Damien George
70a6791b09 shared/runtime/semihosting_arm: Add mp_semihosting_rx_chars.
Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:52:08 +10:00
Damien George
9f9c283ef4 shared/runtime/semihosting_arm: Support semihosting on non-Thumb ARM.
Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:52:08 +10:00
Damien George
c8838b5004 github/workflows: Add CI to run tests against zephyr with qemu.
With this change, the zephyr port is tested against the standard test suite
via the following scheme:
- the zephyr port is built with the `qemu_cortex_m3` board and the
  `prj_minimal.conf` configuration
- `qemu-system-arm` runs `zephyr.elf`
- the zephyr console is redirected to a pts/pty
- `tests/run-tests.py` is run in bare-metal mode against the pts/pty device

This allows testing the zephyr port as though it were a physical board
attached over a serial port.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:23:11 +10:00
Damien George
9af333f2c6 zephyr: Increase CONFIG_CONSOLE_GETCHAR_BUFSIZE to 258.
It needs to be at least this big for `tools/pyboard.py` to work, which is
used (among other things) by `tests/run-tests.py`.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:23:11 +10:00
Damien George
05cad7b56f zephyr: Remove obsolete tinytest test framework.
Commit f573e73bae rewored the zephyr port to
build MicroPython as a cmake target, and since that commit the
`make-bin-testsuite` helper script no longer works (it requires a Makefile)
and hence the tinytest test framework can no longer be run.

Instead of fixing this, remove the option to use tinytest.  Boards running
zephyr can use the standard `tests/run-tests.py` script to run tests in the
usual way.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:23:11 +10:00
Damien George
86aa61918a tests/run-tests.py: Skip additional tests when slice unavailable.
Both of these tests require slice to be enabled.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:23:11 +10:00
Damien George
b095c097e6 tools/pyboard.py: Capture stdout for pts line.
The pts line printed by qemu-system-arm goes to stdout, not stderr.

Redirect stderr to stdout in case other tools do print to stderr.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-28 11:23:11 +10:00
stijn
a8d1c25a1b unix/coveragecpp: Include all API headers in the C++ code.
Make the CI builds compile the public API as C++ to catch accidental
introductions of incompatible code.

Signed-off-by: stijn <stijn@ignitron.net>
2024-08-26 14:11:40 +10:00
Jared Hancock
e901ff8557 extmod/network_wiznet5k: Add support for IPv6.
This adds support for the WIZNET5K nic to use IPv6 with the LWIP stack.
Additionally, if LWIP_IPV6 is disabled, the device is configured to drop
all IPv6 packets to reduce load on the MCU.

Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-08-26 13:02:44 +10:00
Angus Gratton
b82c9ca706 extmod/modtls_mbedtls: Optimise the DER certificate parsing fix.
Small code size and binary size optimisation for the fix merged in
4d6d84983f.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-26 12:48:12 +10:00
iabdalkader
706e09dff3 shared/tinyusb: Allow ports to define CDC TX/RX buffer sizes.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-26 12:42:09 +10:00
Rick Sorensen
260568e081 samd/mcu/samd21: Allow user to enable additional options.
Currently for samd21 some features are disable because of limited memory.
With the ability to trade firmware and filesystem space, a user may wish to
selectively enable some of these features.  This change allows them to be
enabled in board `mpconfigboard.h` or on the build command line for
example.  The selectively enable functions are: MICROPY_PY_FRAMEBUF,
MICROPY_PY_SELECT, MICROPY_PY_ONEWIRE and MICROPY_PY_ASYNCIO.

Signed-off-by: Rick Sorensen <rick.sorensen@gmail.com>
2024-08-26 12:32:37 +10:00
Christian Walther
0b7f6e1d3d py/mkrules.mk: Fix 'make submodules' when building out-of-tree.
When MicroPython is used as a submodule and built from the containing
project, e.g. for the embed port, `make submodules` fails because it goes
looking for the sub-sub-module paths in the outer repository instead of in
the micropython repository. Fix this by invoking git inside the micropython
submodule.

Signed-off-by: Christian Walther <cwalther@gmx.ch>
2024-08-26 12:30:24 +10:00
nspsck
6c3dc0c0b0 stm32/boards/STM32H7B3I_DK: Fix octo-spi pin configuration.
The original OSPIFLASH settings in the `mpconfigboard.h` contained some
mistakes that prevented the firmware from compiling.  These are now
corrected and the firmware can be built with support for OSPI flash.

Note: external storage in OSPI flash is not yet configured on this board.

Signed-off-by: nspsck <teng.jiang94@gmail.com>
2024-08-22 12:35:12 +10:00
nspsck
20a95b249a stm32/system_stm32: Allow selection of OSPI clock source.
Added a #if-block to `system_stm32.c` to check whether
`MICROPY_HW_RCC_OSPI_CLKSOURCE` is defined.  If that is the case, the
clock source for the OSPI will be changed to the specified source.

Signed-off-by: nspsck <teng.jiang94@gmail.com>
2024-08-22 12:29:09 +10:00
nspsck
bd4aaa7333 stm32/octospi: Add OSPI support for STM32H7 MCUs.
Added a if-statement to `octospi.c` to detect if the targeted MCU is one of
the STM32H7 series.  If that is the case, another set of variables are used
for the `mp_hal_pin_config_alt_static_speed()` function, as well as for
register `OCTOSPI1->CR`.  This allows the STM32H723 and STM32H7B3 series
MCU to use octo-spi flash like the STM32H573 series MCU.

Signed-off-by: nspsck <teng.jiang94@gmail.com>
2024-08-22 12:28:52 +10:00
Matt Trentini
e2c0e876f5 stm32/rfcore: Allow HSE to be a wakeup source for BLE for the WB55.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2024-08-22 11:20:15 +10:00
Andrew Leech
185116ea41 stm32/stm32_it: Enable PVD_PVM_IRQHandler for WB and WL MCUs.
There is a gap in support for the PVD interrupt on STM32WBxx and STM32WLxx.
This has been tested on NUCLEO_WB55 with the example code:

    from pyb import Pin, ExtInt

    def callback(line):
        print(line)

    PVD = 16
    exti = ExtInt(PVD, ExtInt.IRQ_RISING_FALLING, Pin.PULL_DOWN, callback)

    exti.swint()

Before this commit the CPU locks up as soon as the final line is run.
After this commit it prints "16".

Fixes issue #15548.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2024-08-20 16:39:37 +10:00
Matt Trentini
5e8d35af08 stm32/boards: Add missing images and update product URLs.
There are some missing images at MicroPython Downloads.  This commit
attempts to resolve all the current issues, and add product URLs where
missing.

Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-08-20 16:14:43 +10:00
Matt Trentini
b704ff66c3 esp32/boards: Remove all IDF3 variants.
IDF 3 builds are very old now (it seems like the last successful builds are
from 2021), and the current IDF 5 is stable.  So remove IDF 3 variants.

Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-08-20 12:49:12 +10:00
Matt Trentini
ad38299779 samd/boards/ADAFRUIT_METRO_M4_EXPRESS: Remove wlan variant.
There is no such variant.

Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-08-20 12:48:46 +10:00
robert-hh
7270b871c2 rp2/modmachine: Set the peripheral frequency with machine.freq().
By default, the peripheral clock for UART and SPI is set to 48 MHz and will
not be affected by the MCU clock change.  This can be changed by a second
argument to `machine.freq(freq, peripheral_freq)`.  The second argument
must be either 48 MHz or identical with the first argument.

Note that UART and SPI baud rates may have to be re-configured after
changing the MCU clock.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-20 12:26:45 +10:00
robert-hh
d420b4e478 rp2/main: Set the default clock frequency at boot.
As a side effect, the peripheral clock will be set to 48Mhz and both UART
and I2C will not be affected by CPu speed changed using `machine.freq()`.

With the change the UART baud rate range is 50 to 3_000_000.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-20 12:26:45 +10:00
Phil Howard
26d91b897e rp2/mphalport: Skip core1_entry if thread disabled.
If `MICROPY_PY_THREAD` is set to 0 (ie: a user C module wishes to use core1
exclusively) then the test of `core1_entry` would fail to compile with an
"undeclared identifier" error.  Fix it by wrapping in `MICROPY_PY_THREAD`.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-08-20 12:14:52 +10:00
robert-hh
76dd4facb9 docs/mimxrt/quickref: Add a note about machine.RTC() subseconds.
Telling that subseconds is not supported and returns always 0.  This was
changed in 913f9ad5ad.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-20 12:07:23 +10:00
robert-hh
87adf11dd2 mimxrt/machine_pin: Clear IRQ flag when enabling or disabling IRQ.
Preventing already pending IRQs to fire when not expected.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-20 12:06:25 +10:00
robert-hh
36108a41d0 mimxrt/mimxrt_sdram: Fix pin config and comments.
Signed-off-by: robert-hh <robert@hammelrath.com>
2024-08-20 12:05:59 +10:00
Alessandro Gatti
7d8b2d89cc py/asmrv32: Use REG_TEMP2 whenever possible.
The RV32 emitter used an additional temporary register, as certain code
sequences required extra storage.  This commit removes its usage in all
but one case, using REG_TEMP2 instead.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-08-19 15:53:50 +10:00
Alessandro Gatti
da0e027fa5 py/asmrv32: Emit C.LW opcodes only when necessary.
The RV32 emitter sometimes generated short load opcodes even when it
was not supposed to.  This commit fixes an off-by-one error in its
offset eligibility range calculation and corrects one case of offset
calculation, operating on the raw label index number rather than its
effective offset in the stack (C.LW assumes all loads are
word-aligned).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-08-19 15:53:50 +10:00
Alessandro Gatti
326e1149ec py/asmrv32: Fix short/long jumps scheduling.
The RV32 emitter always scheduled short jumps even outside the emit
compiler pass.  Running the full test suite through the native emitter
instead of just the tests that depend on the emitter at runtime (as in,
`micropython/native_*` and `micropython/viper_* tests`) uncovered more
places where the invalid behaviour was still present.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-08-19 15:53:50 +10:00
Glenn Moloney
6367099f83 py/objstr: Skip whitespace in bytes.fromhex().
Skip whitespace characters between pairs of hex numbers.
This makes `bytes.fromhex()` compatible with cpython.

Includes simple test in `tests/basic/builtin_str_hex.py`.

Signed-off-by: Glenn Moloney <glenn.moloney@gmail.com>
2024-08-19 14:18:34 +10:00
Elvis Pfützenreuter
e9814e987b esp32/boards/LILYGO_TTGO_LORA32: Add OLED rst seq for board v1.0.
Signed-off-by: Elvis Pfützenreuter <epxx@epxx.co>
2024-08-16 16:28:46 +10:00
Matt Trentini
43f40f797f esp32/boards/M5STACK_ATOMS3_LITE: Add M5Stack AtomS3 Lite board.
Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-08-16 16:17:43 +10:00
Angus Gratton
b6a3aa10f5 esp32: Remove the increased stack limit margin for ESP32-C3.
The extra limit for C3 dates from 6823514 which added C3 support.
Measuring the minimum stack margins that can pass the stress tests I
measured 768 bytes for ESP32-S3 and 512 bytes for ESP32-C3 on ESP-IDF
V5.2.2 and similar on V5.0.4. i.e. The ESP32-C3 actually needs less stack
margin not more!

I think the extra margin for ESP32-C3 probably arose from:

1. Some toolchain inefficiency in the IDF V4.x RISC-V compiler codegen,
that has since been improved.

OR

2. The race condition that was fixed in e3955f42 where sometimes the limit
wasn't set correctly at all. This seems to trigger more on C3, presumably
some timing artifact, and I'd believe that some binaries might be more
susceptible than others due to random factors.

OR

3. Commit 6007f3e206 which enabled custom
NLR handling for ESP32-C3.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-16 14:22:51 +10:00
Angus Gratton
6565b3cb34 esp32: Fix Python cstack size for bluetooth irq callbacks.
This value should have been adjusted when the new cstack API was adopted in
e3955f421d, as otherwise the stack limit is too small especially on
ESP32-C3 where the stack limit was 6144 - 2048 - 2048.

Some extra margin is needed for bluetooth irq because invoke_irq_handler()
isn't a top-level task function, NimBLE calls through multiple layers
first. Measuring this overhead on IDF V5.2.2 (by putting an abort() in
invoke_irq_handler() and then measuring the stack size) yielded 672 bytes
on ESP32-S3 and 612 bytes on ESP32-C3, similar to the size reported in
cd66aa05cf.

Sticking with 1024 bytes for added safety margin. This means on Xtensa the
total margin for the BLE task stays the same (2048 bytes) as before
switching to cstack.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-16 13:55:32 +10:00
Alessandro Gatti
0b75e180a3 esp32/mphalport: Print debug strings even before the GIL is ready.
If verbose debugging is enabled there is some stdout output happening
before the GIL is ready (for example, GC initialisation), and the code
assumed that no string printing occurred before the interpreter was fully
initialised.  Printing long strings would operate without holding the GIL,
which would crash if string output would happen too early in the startup
process.

This commit addresses that issue, making sure verbose debugging output will
work even before the interpreter is fully initialised (as if it is not yet
ready there's no GIL to take care of).

Also, the threshold that would indicate whether a string is "long" (and
thus requiring a GIL release/lock operation) or not was hardcoded to 20
bytes.  This commit makes that configurable, maintaining 20 bytes as a
default.

Fixes issue #15408.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-08-16 13:45:03 +10:00
Matt Trentini
092078852e esp32/boards: Remove BLE from list of features for ESP32-S2.
Fixes issue #15618.

Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
2024-08-16 13:36:22 +10:00
Angus Gratton
e71a324c14 esp32: Restore ESP32-C3 brownout detector settings to IDF defaults.
Commit a66bd7a489 added the
ESP32_GENERIC_C3_USB board (now merged with ESP32_GENERIC_C3) and changed
the brownout detector from the default level 7 (~2.51V) to level 4
(~2.92V).

Raising the level again seems to fix random BOD resets on some of the
cheaper ESP32-C3 dev boards (that likely skimp on power supply
capacitance).

Specifically, this change prevents random resets running multi_bluetooth
tests on ESP32-C3 "SuperMini" board.

Also removed from the LOLIN_C3_MINI board as it seems this config is a copy
of the generic one.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-16 13:21:04 +10:00
Angus Gratton
0a11832cdd esp32: Use the ESP-IDF default esp_console config for ESP32-C3.
The ESP-IDF default on C3 is primary UART0, secondary USB serial/jtag.
Previously MicroPython configured the primary as USB Serial/JTAG and
manually worked with the UART0 console. However UART0 console stopped
working this way in v5.2.2.

The big change is that CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is no longer set,
as primary console is UART0. However
CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG is set and IDF provides a
macro CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED which is set if either
primary or secondary esp_console is USB serial/jtag. So need to use that
macro instead.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 15:58:18 +10:00
Angus Gratton
fbb02d3aee esp32: Add support for ESP-IDF v5.2.2.
Keeping older versions, however if the update goes well then these may be
dropped in the future.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 15:58:12 +10:00
Angus Gratton
35a056ad9c esp32/tools: Add metrics_esp32 size comparison script.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 15:58:05 +10:00
Angus Gratton
10601b04ea esp32/boards: Build using newlib nano formatting functions.
Saves code size, MicroPython doesn't appear to rely on any of the missing
formatters (64-bit integers, c99-style named arguments).

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 15:57:52 +10:00
Angus Gratton
74d04c0262 esp32/adc: Use new ADC calibration API in all cases.
Replaces the deprecated ESP32 calibration API with the "line" method
instead.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 15:57:26 +10:00
Angus Gratton
052693e449 esp32/boards: Reduce IRAM usage.
Disable unnecessary IRAM ISR functionality.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 15:57:16 +10:00
Andrea Milazzo
a4f9c0cc2a esp32/adc: Add support for v5.2.1 calibration api.
This new calibration routine exists for S3 in v5.1.1.  It works for all
platforms in 5.2.1.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-08-14 15:57:09 +10:00
Angus Gratton
fb4ae1eeec test/extmod: Fix machine_spi_rate test on ESP32-C3.
Update to the test added in 1e98c4cb75,
changes the SPI pins for ESP32-C3 (IO 18 and 19 are the native USB pins).

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 15:03:27 +10:00
Angus Gratton
a6fa85d8f9 unix: Switch stack limit check to new cstack API.
Necessary to pass CI when testing the V2 preview APIs.

Also adds an extra coverage test for the legacy stackctrl API, to maintain
coverage and check for any regression.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 12:57:27 +10:00
Angus Gratton
fbc19596f0 rp2: Switch to use new cstack API for stack limit checks.
This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 12:57:23 +10:00
Angus Gratton
80616aee71 tests/run-tests.py: Enable stress tests on esp32 port.
Now passing on ESP32-S3 and ESP32-C3.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 12:56:56 +10:00
Angus Gratton
e3955f421d esp32: Fix thread stack limit margin, change to new cstack API.
This change moves that complexity out into the stack checker and fixes the
bug where stack margin wasn't set correctly by ESP32-C3 threads.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 12:56:46 +10:00
Angus Gratton
86f2c285eb py: Add new cstack API for stack checking, with limit margin macro.
Currently the stack limit margin is hard-coded in each port's call to
`mp_stack_set_limit()`, but on threaded ports it's fiddlier and can lead to
bugs (such as incorrect thread stack margin on esp32).

This commit provides a new API to initialise the C Stack in one function
call, with a config macro to set the margin.  Where possible the new call
is inlined to reduce code size in thread-free ports.

Intended replacement for `MP_TASK_STACK_LIMIT_MARGIN` on esp32.

The previous `stackctrl.h` API is still present and unmodified apart from a
deprecation comment.  However it's not available when the
`MICROPY_PREVIEW_VERSION_2` macro is set.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 12:55:45 +10:00
Angus Gratton
6c870dc5ec py/obj: Remove the legacy object API for version 2.
These were changed in v1.11 (2019).  Prepare to remove the compatibility
macros as part of V2 changes.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-14 10:33:52 +10:00
Peter Züger
1473ed4c64 tests/extmod/ssl_keycert.py: Add test for PKCS8 formatted DER key.
Signed-off-by: Peter Züger <zueger.peter@icloud.com>
2024-08-13 17:32:32 +10:00
Peter Züger
4d6d84983f extmod/modtls_mbedtls: Fix DER parsing and calculation of key/cert len.
`mbedtls_pk_parse_key()` expects `key_len` to include the NULL terminator
for PEM data but not for DER encoded data.  This also applies to
`mbedtls_x509_crt_parse()` and `cert_len`.

Since all PEM data contains "-----BEGIN" this is used to check if the data
is PEM (as per mbedtls code).

This can be done for both v2 and v3 of mbedtls since the fundamental
behaviour/expectation did not change.  What changed is that in v3 the
PKCS#8 DER parser now checks that the passed key buffer is fully utilized
and no bytes are remaining (all other DER formats still do not check this).

Signed-off-by: Peter Züger <zueger.peter@icloud.com>
2024-08-13 17:32:32 +10:00
Glenn Moloney
288a036253 esp32/network_lan: Ensure LAN MAC address is valid at LAN init.
`get_lan()`: If the ethernet MAC address is uninitialised, set it to the
address reserved by the ESP32 for the ETH interface.

SPI LAN devices may be initialised with a MAC address of 00:00:00:00:00:00.
So check that a valid unicast MAC address has been set (using
`LAN.config(mac=...)`) when initialising the LAN interface.

Fixes #15425.

Signed-off-by: Glenn Moloney <glenn.moloney@gmail.com>
2024-08-12 16:28:30 +10:00
Glenn Moloney
868d311a23 esp32/network_lan: Make LAN.active(state) succeed if already in state.
This PR ensures that `network.LAN.active(True/False)` will succeed if the
LAN is already in the desired state.

Currently, `lan.active(True)` will raise an `OSError` exception if the LAN
is already in the desired state.  This is inconsistent with
`network.WLAN.active(True/False)` and causes `lan.active(True)` to raise an
exception after a soft reset (causing common network startup scripts to
fail for LAN interfaces).

Signed-off-by: Glenn Moloney <glenn.moloney@gmail.com>
2024-08-12 16:13:21 +10:00
iabdalkader
91f4a6b9e9 mimxrt/mpmetalport: Use mp_event_handle_nowait() for metal_poll.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 18:02:21 +10:00
iabdalkader
67ebe086a8 stm32/mpmetalport: Use mp_event_handle_nowait() for metal_poll.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 18:02:21 +10:00
iabdalkader
1743a7d721 extmod/modopenamp: Use mp_event_* functions for poll/wait.
These are the new helper functions to use for polling/waiting.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 18:02:21 +10:00
iabdalkader
9a48ce3051 stm32/mpu: Define the last used MPU region number.
The reason for this change is that it makes allows custom code, that needs
to use an MPU region, to find a free one by using this macro or starting
from the max number and downwards, without concern that it might change in
the future.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 18:02:13 +10:00
iabdalkader
bc7e39d549 extmod/modopenamp: Fix Endpoint callback required arg.
The callback arg is not actually required.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 17:59:50 +10:00
iabdalkader
7f49897ada extmod/modopenamp: Add support for building Open-AMP on device side.
Tested with two VMs each running on a different core.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 17:59:32 +10:00
iabdalkader
4350cbcb48 extmod/modopenamp_remoteproc: Fix entry point address int overflow.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 17:59:17 +10:00
iabdalkader
1216f2c313 extmod/libmetal: Remove source file listed twice in sources.
This causes multiple definition of symbols on some builds.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-08-08 17:59:06 +10:00
Alessandro Gatti
55b2720687 shared/runtime/gchelper: Add RISC-V RV64I native gchelper.
Add native gchelper support for 64 bits RISC-V RV64I targets.

Now that RV64 is under CI, this also enables platform-specific ghelper
in the Unix port.

Also changes the data type holding the register contents to something more
appropriate, so in the remote eventuality somebody wants to use this with
RV128 all they have to do is update the `__riscv_xlen` check.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-08-07 16:23:21 +10:00
Damien George
aa0b8f340d mpy-cross/main: Use MICROPY_BANNER_NAME_AND_VERSION for --version.
Gives the same output and keeps things consistent across the code base.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-07 16:03:29 +10:00
Damien George
1fe3b47c81 qemu-arm: Fix tinytest test profile when updating set of dirs/files.
Updating a set must use `.update()` rather than `.add()`.

Also apply the same pattern to qemu-riscv to prevent the same issue when
directories/files are added to that port's `tests_profile.txt` file.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-07 15:20:53 +10:00
Angus Gratton
1e98c4cb75 tests/extmod: Add machine_spi_rate test.
Based on machine_i2s_rate, allows testing basic SPI functionality and
timings.

Implemented and confirmed working for rp2, esp32, and pyboard.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-07 15:07:13 +10:00
Damien George
a4b3825bd4 tests/extmod: Rename machine_timer exp file to machine_soft_timer.
This was missed in 9ba04cc756

Signed-off-by: Damien George <damien@micropython.org>
2024-08-07 15:02:52 +10:00
Damien George
5ff6c12c65 esp32/main: Store native code as linked list instead of list on GC heap.
Finalisers that run during `gc_sweep_all()` may run native code, for
example if an open file is closed and the underlying block device is
implemented in native code, then the filesystem driver (eg FAT) may call
into the native code.

Therefore, native code must be freed after the call to `gc_sweep_all()`.
That can only be achieved if the GC heap is not used to store the list of
allocated native code blocks.  Instead, this commit makes the native code
blocks a linked list.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-07 14:19:18 +10:00
Angus Gratton
6fead31832 esp32: Enable workaround for math.gamma(-inf) result.
Without this commit, math.gamma(-float("inf")) returns inf instead of
raising a math domain ValueError. Needed for float/math_domain_special.py
test to pass on esp32.

Root cause is an upstream libm bug, has been reported to ESP-IDF.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-07 14:10:46 +10:00
Angus Gratton
b0c89377d0 py/modmath: Add option to work around -inf bug in a port's tgamma.
This is needed for a workaround on esp32 port (in child commit),
which produces incorrect results otherwise.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-07 14:10:46 +10:00
Damien George
afba3e0540 py/emitnative: Fix case of clobbered REG_TEMP0 when loading const obj.
The `emit_load_reg_with_object()` helper function will clobber `REG_TEMP0`.
This is currently OK on architectures where `REG_RET` and `REG_TEMP0` are
the same (all architectures except RV32), because all callers of
`emit_load_reg_with_object()` use either `REG_RET` or `REG_TEMP0` as the
destination register.  But on RV32 these registers are different and so
when `REG_RET` is the destination, `REG_TEMP0` is clobbered, leading to
incorrectly generated machine code.

This commit fixes the issue simply by using `REG_TEMP0` as the destination
register for all uses of `emit_load_reg_with_object()`, and adds a comment
to make sure the caller of this function is careful.

Signed-off-by: Damien George <damien@micropython.org>
2024-08-07 12:25:21 +10:00
Phil Howard
d2e33fe309 rp2/machine_i2s: Deinit all active I2S instances on soft reset.
Add `machine_i2s_deinit_all` to teardown any active I2S instances on soft
reset.  Prior to this fix, code using I2S required a try/finally in order
to avoid a hard fault on soft reset.

Fixes issue #14339.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-08-07 12:01:34 +10:00
Phil Howard
ad3552ae2c rp2/rp2_pio: Make PIO IRQ handlers have lazy initialisation.
This change has no impact on vanilla MicroPython builds, but is intended to
avoid RP2's PIO implementation from trampling PIO usage in USER_C_MODULES.

This is consistent with PIOs tracking of used state machines and managed
programs, and makes working with PIO in USER_C_MODULES much less of an
uphill battle.

Since PIO deinit runs before gc_sweep_all it's impossible to work around
this wrinkle otherwise.  A module finalizer does not get the opportunity to
put the PIOs back into a state which wont crash rp2_pio_deinit.

Changes are:
- init: Avoid exclusive handlers being added to all PIOs and add them only
  when needed.
- deinit: Only remove handlers we have set.
- rp2_pio_irq: Add the exlusive handler if needed.
- rp2_state_machine_irq: Add the exclusive handler if needed.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-08-02 16:27:42 +10:00
Phil Howard
e7ff0b8a31 rp2/memmap_mp.ld: Lower the minimum GC heap to 32K.
Reduce mimimum heap requirement.  This value allows more room for large,
static buffers in user C modules (such as graphics buffers or otherwise)
which might be allocated outside of MicroPython's heap to guarantee
alignment or avoid fragmentation.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-08-02 16:21:36 +10:00
Phil Howard
1557014ea4 rp2/boards/PIMORONI_TINY2040: Add an 8MB variant to Tiny 2040.
Add an 8MB "PIMORONI_TINY2040" variant.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-08-02 16:17:48 +10:00
Phil Howard
cd1ab7645e rp2/boards/PIMORONI_PICOLIPO: Refactor Pico LiPo to use board variants.
Combine the 4MB and 16MB "PIMORONI_PICOLIPO" variants into a single board.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-08-02 16:17:24 +10:00
Phil Howard
11becbe223 rp2/CMakeLists.txt: Add MICROPY_DEF_BOARD to compile definitions.
Add MICROPY_DEF_BOARD as per esp32 port, allows board variants to override
the board name with:

    list(APPEND MICROPY_DEF_BOARD
        MICROPY_HW_BOARD_NAME="New Board Name"
    )

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-08-02 16:16:23 +10:00
Angus Gratton
6d05424754 tests/extmod: Add esp32 support to the machine_i2s_rate test.
This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-02 10:31:19 +10:00
Angus Gratton
0d00d72b76 esp32/machine_i2s: Ensure 2 DMA buffers and improve I2S error handling.
ESP-IDF driver always requires at least two DMA buffers, so ensure that's
the case.

Failures during initialisation were being lost because ESP_ERROR_CHECK is
configured as a no-op, so the failure was deferred until read() or write()
was called on the port.  Raise an error from init, instead.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-02 10:30:14 +10:00
Angus Gratton
9ba04cc756 tests/extmod: Skip soft machine.Timer test on esp32 port.
Also rename the test to reflect that it's a soft timer test.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-02 10:27:53 +10:00
Tim Weber
d1685a3f5f docs/library/neopixel: Mention bitstream timing tuple.
Signed-off-by: Tim Weber <scy@scy.name>
2024-08-01 12:04:58 +10:00
George Hopkins
066243ea74 py/py.mk: Add SRC_USERMOD_LIB_ASM to include assembly files.
Introduce SRC_USERMOD_LIB_ASM to allow users to include assembly files as
part of their user modules.  It could be used to include optimized
functions or outputs of other programming languages.

Signed-off-by: George Hopkins <george-hopkins@null.net>
2024-08-01 12:01:18 +10:00
Angus Gratton
1754c587f9 esp32: Fix heap corruption triggered by bluetooth.active(0).
It seems like at some point Espressif NimBLE team changed
nimble_port_init and nimble_port_deinit to manage HCI init
internally:
https://github.com/espressif/esp-nimble/commit/f8a79b04c9743543b8959727d7

This change is included in all the IDF versions that MicroPython supports.

As a result, existing code that called esp_nimble_hci_deinit() explicitly
would trigger a use-after-free bug and heap corruption (specifically this
calls through to ble_transport_deinit() which calls os_mempool_free(). The
second time this writes out to a bunch of memory pools where the backing
buffers have already been freed.)

Symptoms were intermittent random crashes after de-activating Bluetooth
(running multi_bluetooth/ble_gatt_data_transfer.py could sometimes
reproduce). Setting Heap Poisoning to Comprehensive in menuconfig caused
the bug to be detected every time.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-08-01 11:01:05 +10:00
iabdalkader
6f27e1c968 lib/arduino-lib: Update submodule to the latest.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-07-31 16:51:13 +10:00
iabdalkader
a3100be4b2 stm32/boards: Swap FMC banks on ARDUINO_GIGA and ARDUINO_PORTENTA_H7.
Swap FMC banks to remap the SDRAM bank1 address to 0x60000000.  Arduino's
M4 firmware uses address 0x60000000 by default.  When the elf loader tries
to load that it will fail because by default NOR/PSRAM is mapped at that
address, not SDRAM bank1.  (Note that the region at 0xC0000000 has an XN
attribute by default, so switching the M4 firmware address will not work.)

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-07-31 16:47:32 +10:00
Andrew Leech
70a7e0ff2f nrf/Makefile: Fix GCC_VERSION check.
Previously it was truncating the first digit of the version if the major
number had more than one digit.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-07-31 12:44:16 +10:00
Alessandro Gatti
6007f3e206 esp32/mpconfigport: Enable the RV32 emitter for ESP32C3 targets.
The RV32 code emitter assumed that the arch-specific NLR was used
instead of the setjmp/longjmp based NLR code.  If the latter NLR
provider was chosen, the emitter would allocate space on the stack
for the NLR buffer but would not fill it in.

This change turns off setjmp()-based NLR and GCREGS for the ESP32C3
target, in favour of more platform-tailored alternatives.  As setjmp()
NLR is now disabled by default, the RV32 emitter can be safely enabled
by default as well for the target in question.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-07-26 12:13:03 +10:00
robert-hh
4a134d212e nrf/modules/machine/pin: Disable IRQ with pin.irq(handler=None).
Before, the input was still set to `pin.irq()` mode, only the handler was
disabled.  That prevented switching the pin between input and output mode.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-07-26 11:32:49 +10:00
Andrew Leech
5e80416e6d nrf/modules/machine/soft_pwm: Ensure duty_width is always valid.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-07-26 11:14:19 +10:00
Andrew Leech
62e0fa04a7 nrf/Makefile: Enable LTO by default only on newer gcc.
Older gcc/binutils linker does not support lto with wrap.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-07-26 11:13:11 +10:00
Andrew Leech
56c1617384 nrf/modules/machine/uart: Support sending data stored in flash.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-07-26 11:12:46 +10:00
Andrew Leech
19075695da nrf: Consolidate all stdio functions.
Consolidate CDC, UART and NUS stdio interfaces into the one handler.
Allows any/all of them to be enabled separately.

Updates UART REPL to use similar define to other platforms:
`MICROPY_HW_ENABLE_UART_REPL`.

USB now uses the shared/tinyusb CDC implementation.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-07-26 11:10:32 +10:00
Damien George
e1fe62f4fc tests/multi_net: Fix skipping of SSLContext tests when .der don't exist.
The `sslcontext_server_client_ciphers.py` test was using stat to test for
the .der files after it already tried to open them for reading.  That is
now fixed.  And `sslcontext_server_client.py` is adjusted to use the same
pattern for skipping the test.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-25 18:14:52 +10:00
Alessandro Gatti
17f254df35 github/workflows: Add RISC-V 64 bits Unix port to CI.
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-07-25 16:45:04 +10:00
stijn
1f907a2f5c tests/run-tests.py: Make Windows test skipping more granular.
Signed-off-by: stijn <stijn@ignitron.net>
2024-07-25 16:24:04 +10:00
stijn
a0c7bf12d2 github/workflows: Improve MSYS2-based CI builds.
Install the mingw variant of Python since it behaves more like a 'real'
Windows CPython than the msys2 variant: os.name == 'nt', not 'posix'.  Note
that os.sep is still '/' though so we don't actually need to skip the
import_file test.  This way one single Python version can be used both for
running run-tests.py and getting the expected test output.

Signed-off-by: stijn <stijn@ignitron.net>
2024-07-25 16:22:21 +10:00
Damien George
233f5ce661 py/runtime: Fix self arg passed to classmethod when accessed via super.
Thanks to @AJMansfield for the original test case.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-25 13:07:42 +10:00
stijn
07bf3179f6 py/misc: Fix msvc and C++ compatibility.
Use explicit casts to suppress warnings about implicit conversions, add a
workaround for constant expression conditional, and make functions static
inline (as is done in the rest of the codebase) to suppress 'warning C4505:
unreferenced function with internal linkage has been removed'.

(Follow up to fix commit 908ab1ceca)

Signed-off-by: stijn <stijn@ignitron.net>
2024-07-25 12:55:23 +10:00
stijn
093d0c0a17 py/objtype: Validate super() arguments.
This fixes various null dereferencing and out-of-bounds access because
super_attr assumes the held obj is effectively an object of the held type,
which is now verified.

Fixes issue #12830.

Signed-off-by: stijn <stijn@ignitron.net>
2024-07-25 12:27:33 +10:00
David Lechner
d1bf0eeb0f tests/cpydiff: Add diff for overriding __init__.
This adds a CPython diff that explains why calling `super().__init__()` is
required in MicroPython when subclassing a native type (because `__new__`
and `__init__` are not separate functions).

Signed-off-by: David Lechner <david@pybricks.com>
2024-07-25 12:01:43 +10:00
Laurens Valk
9ca668f881 py/objtype: Avoid crash on calling members of uninitialized native type.
When subclassing a native type, calling native members in `__init__` before
`super().__init__()` has been called could cause a crash.  In this
situation, `self` in `mp_convert_member_lookup` is the
`native_base_init_wrapper_obj`.  The check added in this commit ensures
that an `AttributeError` is raised before this happens, which is consistent
with other failed lookups.

Also fix a typo in a related comment.

Signed-off-by: Laurens Valk <laurens@pybricks.com>
2024-07-25 12:01:43 +10:00
Laurens Valk
19b1333cb1 examples/usercmodule/cexample: Add more advanced native class.
This adds a separate `AdvancedTimer` class that demonstrates a few more
advanced concepts usch as custom handlers for printing and attributes.

Signed-off-by: Laurens Valk <laurens@pybricks.com>
2024-07-25 11:57:13 +10:00
Felix Dörre
7fe8f030ee rp2/lwip_inc: Enable IPv6 per default on rp2 port.
Having IPv6 support is important, especially for IoT-Devices which might be
many, requiring individual IP-addresses. In particular direct access via
link-local addresses and having deterministic SLAAC-addresses can be quite
convenient. Also in IPv6-only networks or for connecting to IPv6-only
services, this is very useful.

For the Pico W, there is enough flash and RAM that enabling IPv6 by default
is the right choice.

Should IPv6 support in a network exist (i.e. there are Router
Advertisements), but not provide connectivity, connecting by domain name
should not be a problem as DNS will default to return the IPv4-address (if
that exists), unless reconfigured at runtime to prefer IPv6.

In any case a user can disable obtaining SLAAC-addresses with:

    <nic>.ipconfig(autoconf6=False)

Signed-off-by: Felix Dörre <felix@dogcraft.de>
2024-07-24 14:59:01 +10:00
Angus Gratton
ba98533454 rp2: Stop machine.idle() blocking indefinitely.
Updates rp2 port to always resume from idle within 1ms max.

When rp2 port went tickless the behaviour of machine.idle() changed as
there is no longer a tick interrupt to wake it up every millisecond. On a
quiet system it would now block indefinitely. No other port does this.

See parent commit for justification of why this change is useful.

Also adds a test case that fails without this change.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-07-23 16:46:27 +10:00
Angus Gratton
81daba31c5 docs: Specify that machine.idle() returns at least every 1ms.
A lot of existing code (i.e. micropython-lib lps22h, lcd160cr sensor
drivers, lora sync_modem driver, usb-device-hid) calls machine.idle()
inside a tight loop that is polling some condition. This reduces the power
usage compared to constantly looping, but can be faster than calling a
sleep function. However on a tickless port there's not always an interrupt
before the condition they are polling for, so it's difficult to restructure
this code if machine.idle() doesn't have any upper limit on execution time.

This commit specifies an upper limit of 1ms before machine.idle() resumes
execution. This is already the case for all ports except rp2.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-07-23 16:42:42 +10:00
Phil Howard
e1ecc232dc rp2/rp2_pio: Disable correct IRQ for PIO1.
Fix a typo that was disabling PIO0_IRQ_1 instead of PIO1_IRQ_0.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-07-23 16:15:40 +10:00
Angus Gratton
9db16cfe31 rp2: Fix wakeup from WFE on core1.
If core1 executes `mp_wfe_or_timeout()` then it needs to receive an
interrupt or a SEV to resume execution, but the soft timer interrupt only
fires on core 0.  This fix adds a SEV to the soft timer interrupt handler.

This issue was masked by the issue fixed in the previous commit, as WFE
previously wasn't suspending properly.

Verified via the existing thread_sleep2 test.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-07-23 16:02:59 +10:00
Angus Gratton
eced9d86a7 rp2: Fix power consumption when sleeping with a timeout.
Fixes a regression introduced in 3af006efb3
where WFE never blocked in `mp_wfe_or_timeout()` function and would
busy-wait instead.  This increases power consumption measurably.

Root cause is that `mp_wfe_or_timeout()` calls soft timer functions that
(after the regression) call `recursive_mutex_enter()` and
`recursive_mutex_exit()`.  The exit calls
`lock_internal_spin_unlock_with_notify()` and the default pico-sdk
implementation of this macro issues a SEV which negates the WFE that
follows it, meaning the CPU never suspends.

See https://forums.raspberrypi.com/viewtopic.php?p=2233908 for more
details.

The fix in this comment adds a custom "nowait" variant mutex that doesn't
do WFE/SEV, and uses this one for PendSV.  This will use more power when
there's contention for the PendSV mutex as the other core will spin, but
this shouldn't happen very often.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-07-23 16:01:42 +10:00
Alessandro Gatti
44527ada5f unix/main: Fix GCC builds for RISC-V 64 bits.
This contains a workaround to silence a possibly incorrect warning when
building the Unix port with GCC targeting RISC-V 64 bits.

Fixes issue #12838.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-07-23 15:51:50 +10:00
robert-hh
594c4229b7 esp32/machine_timer: Limit timer numbers for ESP32C3.
The ESP32C3 has only two timers in one group.  In the code this is
reflected as two groups with one timer.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-07-23 14:55:35 +10:00
Angus Gratton
46c3df0229 tests/run-tests.py: Enable thread tests on esp32.
Before the fix in parent commit, some of these tests hung indefinitely.

After, they seem to consistently pass.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-07-23 12:34:14 +10:00
Angus Gratton
337742f6c7 esp32/mpthreadport: Fix uneven GIL allocation between Python threads.
Explicitly yield each time a thread mutex is unlocked.

Key to understanding this bug is that Python threads run at equal RTOS
priority, and although ESP-IDF FreeRTOS (and I think vanilla FreeRTOS)
scheduler will round-robin equal priority tasks in the ready state it does
not make a similar guarantee for tasks moving between ready and waiting.

The pathological case of this bug is when one Python thread task is busy
(i.e. never blocks) it will hog the CPU more than expected, sometimes for
an unbounded amount of time. This happens even though it periodically
unlocks the GIL to allow another task to run.

Assume T1 is busy and T2 is blocked waiting for the GIL. T1 is executing
and hits a condition to yield execution:

1. T1 calls MP_THREAD_GIL_EXIT
2. FreeRTOS sees T2 is waiting for the GIL and moves it to the Ready list
   (but does not preempt, as T2 is same priority, so T1 keeps running).
3. T1 immediately calls MP_THREAD_GIL_ENTER and re-takes the GIL.
4. Pre-emptive context switch happens, T2 wakes up, sees GIL is not
   available, and goes on the waiting list for the GIL again.

To break this cycle step 4 must happen before step 3, but this may be a
very narrow window of time so it may not happen regularly - and
quantisation of the timing of the tick interrupt to trigger a context
switch may mean it never happens.

Yielding at the end of step 2 maximises the chance for another task to run.

Adds a test that fails on esp32 before this fix and passes afterwards.

Fixes issue #15423.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-07-23 12:33:19 +10:00
Junwha
2994354634 extmod/vfs: Fix buffer overflow of string comparison in umount.
The comparison between the given unmount string and existing mount strings
were made by the given string, which leads to buffer overflow.

Fixes issue #13006.

Signed-off-by: Junwha <qbit@unist.ac.kr>
2024-07-23 12:13:49 +10:00
Terence Stenvold
390390ec37 extmod/vfs_fat: Set default volume label on mkfs if it's defined.
Using mkfs doesn't set a volume label for FAT filesystems.  This commit
will set the volume label if `MICROPY_HW_FLASH_FS_LABEL` is defined.
2024-07-23 11:39:17 +10:00
stijn
444d7bacbe extmod/moductypes: Validate the descriptor tuple.
Fixes various null dereferencing, out-of-bounds memory accesses and
`assert(0)` failures in the case of an invalid `uctypes` descriptor.

By design `uctypes` can crash because it accesses arbitrary memory, but at
least describing the descriptor layout should be forced to be correct and
not crash.

Fixes issue #12702.

Signed-off-by: stijn <stijn@ignitron.net>
2024-07-22 14:40:45 +10:00
Michael Vornovitsky
6db91dfefb extmod/modbtree: Add checks for already-closed database.
Fixes use-after-free when accessing the database after it is closed with
`btree_close`.  `btree_close` always succeeds when called with an
already-closed database.

The new test checks that operations that access the underlying database
(get, set, flush, seq) fail with a `ValueError` when the btree is already
closed.  It also checks that closing and printing the btree succeed when
the btree is already closed.

Fixes issue #12543.

Signed-off-by: Michael Vornovitsky <michaelvornovitskiy@outlook.com>
2024-07-22 10:42:29 +10:00
Damien George
8159dcc276 extmod/modos: Include os.sep entry if MICROPY_VFS is enabled.
This simplifies configuration by removing the `MICROPY_PY_OS_SEP` option
and instead including `os.sep` if `MICROPY_VFS` is enabled.  That matches
the configuration of all existing ports that enabled `os.sep` (they also
had `MICROPY_VFS` enabled), and brings consistency to other ports.

Fixes issue #15116.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-20 12:32:31 +10:00
Damien George
5f3ecc29f8 extmod/modmachine: Use sys.exit as implementation of machine.soft_reset.
It does the same thing, raising `SystemExit`.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-20 12:18:07 +10:00
Damien George
69c25ea865 shared/runtime/pyexec: Make a raised SystemExit always do a forced exit.
The current situation with SystemExit and soft reset is the following:
- `sys.exit()` follows CPython and just raises `SystemExit`.
- On the unix port, raising `SystemExit` quits the application/MicroPython,
  whether at the REPL or in code (this follows CPython behaviour).
- On bare-metal ports, raising `SystemExit` at the REPL does nothing,
  raising it in code will stop the code and drop into the REPL.
- `machine.soft_reset()` raises `SystemExit` but with a special flag set,
  and bare-metal targets check this flag when it propagates to the
  top-level and do a soft reset when they receive it.

The original idea here was that a bare-metal target can't "quit" like the
unix port can, and so dropping to the REPL was considered the same as
"quit".  But this bare-metal behaviour is arguably inconsistent with unix,
and "quit" should mean terminate everything, including REPL access.

This commit changes the behaviour to the following, which is more
consistent:
- Raising `SystemExit` on a bare-metal port will do a soft reset (unless
  the exception is caught by the application).
- `machine.soft_reset()` is now equivalent to `sys.exit()`.
- unix port behaviour remains unchanged.

Tested running the test suite on an stm32 board and everything still
passes, in particular tests that skip by raising `SystemExit` still
correctly skip.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-20 12:13:14 +10:00
robert-hh
a734ee9057 shared/tinyusb/mp_usbd_cdc: Skip writing to an uninitialized USB device.
During execution of `boot.py` the USB device is not yet initialized.  Any
attempt to write to the CDC (eg calling `print()`) would lock up the
device.  This commit skips writing when the USB device is not initialized.
Any output from `boot.py` is lost, but the device does not lock up.

Also removed unnecessary declaration of `tusb_init()`.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-07-20 00:27:58 +10:00
Damien George
847ee20d9b tests/multi_bluetooth/perf_gatt_notify.py: Reduce connection interval.
To test that the notification ping-pong can be low latency.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-19 22:28:31 +10:00
Damien George
77bd8fe5b8 webassembly: Reuse PyProxy objects when they are the same Python object.
This commit makes it so that PyProxy objects are reused (on the JavaScript
side) when they correspond to an existing Python object that is the same
object.

For example, proxying the same Python function to JavaScript, the same
PyProxy instance is now used.  This means that if `foo` is a Python
function then accessing it on the JavaScript side such as
`api.globals().get("foo")` has the property that:

    api.globals().get("foo") === api.globals().get("foo")

Prior to this commit the above was not true because new PyProxy instances
were created each time `foo` was accessed.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-19 11:55:24 +10:00
Damien George
5147dc5de5 py/gc: Remove commented-out functions.
These are old, unused, and most of them no longer compile.  The `gc_test()`
function is superseded by the test suite.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-19 10:36:30 +10:00
Damien George
1548132979 py/sequence: Remove unused len argument from mp_seq_extract_slice.
Also put this function inside the `MICROPY_PY_BUILTINS_SLICE` guard,
because it's only usable when that option is enabled.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-18 12:51:29 +10:00
Damien George
96007e7de5 py/lexer: Add static assert that token enum values all fit in a byte.
Signed-off-by: Damien George <damien@micropython.org>
2024-07-18 12:44:44 +10:00
Damien George
e00d80d9e2 py: Remove 5 TODOs in emitbc, objrange and repl.
These TODOs don't need to be done:

- Calling functions with keyword arguments is less common than without
  them, so adding an extra byte overhead to all calls regardless of whether
  they use keywords or not would overall increase generated bytecode size.

- Restricting `range` objects to machine-sized ints has been adequate for
  a long time now, so no need to change that and make it more complicated
  and slower.

- Printing spaces in tab completion does not need to be optimised.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-18 12:35:42 +10:00
Damien George
fce3cea244 tests/extmod: Make get_event_loop tests compatible with CPython 3.12.
Follow up to 2e852522b1: instead of having
.exp files for the get_event_loop tests, tweak them so they are compatible
with CPython 3.12.  This requires calling `asyncio.set_event_loop()` so
there is an active event loop and `asyncio.get_event_loop()` succeeds
without a warning.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-18 11:08:48 +10:00
Damien George
b4b4d161c2 unix/mpbtstackport_usb: Remove thread detached attribute.
As in the previous commit, the thread is later joined so can't be detached.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-17 15:02:57 +10:00
Leo Chung
220088fff6 unix/mpbthciport: Remove thread detached attribute.
A detached thread is not joinable, and the behavior maybe undefined.

Signed-off-by: Leo Chung <gewalalb@gmail.com>
2024-07-17 15:01:04 +10:00
Lennart
55e75c4ad4 unix/modtermios: Add more baudrate options.
This adds some more baudrate option as they are available in the termios.h
header - up to a point that seems reasonable in an embedded context.

Signed-off-by: Lennart Schierling <Lennart@binarylabs.dev>
2024-07-15 11:27:23 +10:00
Damien George
abbce268af github/workflows: Use macos-latest for unix macos CI.
macos-11.0 is no longer available.

With this change in the macos version, some tests which previously failed
now pass, and some different tests now fail.  Exclude those that fail from
the CI until they can be fixed properly.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-15 11:10:00 +10:00
Owen
4fdad8eabe extmod/modre: Rename re_exec to re_exec_helper to avoid clash on BSD.
The `re_exec` symbol is the name of a FreeBSD regex function, so needs to
be renamed to avoid a clash when building on FreeBSD.  (This clash was
fixed once before but then accidentally reintroduced by the u-module
renaming in 7f5d5c72718af773db751269c6ae14037b9c0727.)

Fixes issue #15430.

clarify as helper function
2024-07-15 10:57:44 +10:00
robert-hh
ee1036023e extmod/machine_spi: Support firstbit=LSB for machine.SoftSPI.
Being able to send data out in LSB format can be useful, and having support
in the low-level driver is much better than requiring Python code to
reorder the bits before sending them / after receiving them.  In particular
if the hardware does not support the LSB format (eg RP2040) then one needs
to use the SoftSPI in LSB mode.

For this change a default definition of `MICROPY_PY_MACHINE_SPI_MSB/_LSB`
was added to `py/mpconfig.h`, making them available to all ports.  The
identical defines in `esp32/mpconfigport.h` were deleted.

Resolves issues #5340, #11404.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-07-12 22:59:31 +10:00
iabdalkader
20b00ca501 extmod/network_nina: Fix the AP security mode constants.
The only AP security mode supported is actually WPA/WPA2 not WEP. The
firmware command `0x19` starts the AP using `WIFI_AUTH_WPA_WPA2_PSK`
mode.

There are no functional changes in this commit, it just fixes the constant
names and removes the useless sanity checks for WEP.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-07-12 01:03:46 +10:00
robert-hh
2be45dd682 extmod/modmachine: Allow more than one argument to machine.freq().
The limit is set by a `MICROPY_PY_MACHINE_FREQ_NUM_ARGS_MAX` define, which
defaults to 1 and is set for stm32 to 4.

For stm32 this fixes a regression introduced in commit
e1ec6af654 where the maximum number of
arguments was changed from 4 to 1.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-07-11 23:38:07 +10:00
Damien George
358e501e75 tests/stress/bytecode_limit.py: Make test more robust with low memory.
A target may have enough RAM to run the n=433 test but then run out of RAM
on the n=432 test.  So allow the test to skip on the n=432 case before it
prints any output.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-05 17:07:30 +10:00
Damien George
633586a716 tests/thread/stress_aes.py: Fix logic waiting for finished threads.
Because the main thread executes `thread_entry()` it means there's an
additional one added to `count`, so the test must wait for the count to
reach `n_thread + 1`.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-05 17:07:27 +10:00
Felix Dörre
4d16a9cced docs: Update docs to replace ifconfig with ipconfig.
Follow up to 1c6012b0b5

Signed-off-by: Felix Dörre <felix@dogcraft.de>
2024-07-05 16:06:04 +10:00
Damien George
0b58d02f70 esp32,esp8266: Use new mp_obj_new_str_from_cstr() function.
These were missed in the previous commit.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-05 11:27:25 +10:00
Jon Foster
92484d8822 all: Use new mp_obj_new_str_from_cstr() function.
Use new function mp_obj_new_str_from_cstr() where appropriate.  It
simplifies the code, and makes it smaller too.

Signed-off-by: Jon Foster <jon@jon-foster.co.uk>
2024-07-04 15:55:03 +10:00
Jon Foster
289b2dd879 py/objstr: Add new mp_obj_new_str_from_cstr() helper function.
There were lots of places where this pattern was duplicated, to convert a
standard C string to a MicroPython string:

    x = mp_obj_new_str(s, strlen(s));

This commit provides a simpler method that removes this code duplication:

    x = mp_obj_new_str_from_cstr(s);

This gives clearer, and probably smaller, code.

Signed-off-by: Jon Foster <jon@jon-foster.co.uk>
2024-07-04 15:52:47 +10:00
robert-hh
f36a5654a8 docs/rp2/quickref: Document the use of channel numbers for ADC.
Signed-off-by: robert-hh <robert@hammelrath.com>
2024-07-04 11:50:47 +10:00
robert-hh
2b8de7436b rp2/machine_adc: Initialise ADC GPIO when a Pin is referenced by int.
The change closes the gap in the API when an integer is used as Pin
reference.  With the change, e.g. ADC(26), ADC(Pin(26)) and ADC("GP26")
behave identically and the GPIO is initialised in ACD/high-Z mode.

Only when using ADC channel numbers 0-3 are the corresponding GPIO left
uninitialised, and then the user is responsible for configuring the GPIO.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-07-04 11:50:28 +10:00
Phil Howard
f61fac0ba6 rp2/rp2_pio: Replace explicit pio ternary expression with pio_get_index.
There are three changes here:
- Fix `rp2_pio_print` to use `pio_get_index()` too, since it had its own
  copy of the ternary expression.
- Remove a ternary from `rp2_pio_state_machine` and calculate it from
  `pio_get_index`.
- Remove a ternary on `GPIO_FUNC_PIO0` vs `GPIO_FUNC_PIO1`.  These
  constants are sequentially ordered so we can calculate them too.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2024-07-03 16:48:18 +10:00
Phil Howard
462fa5f94f rp2/rp2_pio: Replace PIO_NUM macro with pio_get_index.
The `PIO_NUM` macro was defined when `rp2_pio.c` was first conceived.
There's now a Pico SDK function for this, `pio_get_index()`, which is
already used in some parts of the code.

This commit removes `PIO_NUM` in favour of using `pio_get_index()`
everywhere.

Signed-off-by: Phil Howard <github@gadgetoid.com>
2024-07-03 16:48:15 +10:00
Damien George
75350f9c8e rp2/mbedtls: Remove config options that are now in the common settings.
Signed-off-by: Damien George <damien@micropython.org>
2024-07-02 13:22:51 +10:00
Sylvain Zimmer
838794ebcc extmod/mbedtls: Enable GCM and ECDHE-RSA in common mbedtls config.
Enable support for cipher suites like
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, as suggested in
https://github.com/micropython/micropython/issues/14204#issuecomment-2024366349
and https://github.com/micropython/micropython/issues/10485#issuecomment-1396426824

Tests have been run on the top 500 domains from moz.com.  Without this
patch, 155 out of 500 fail to connect because of TLS issues.  This patch
fixes them all.  And it seems all existing mbedtls flags are needed to get
good coverage of those top 500 domains.

The `ssl_poll.py` test has the cipher bits increased from 512 to 1024 in
its test key/cert so that it can work with ECDHE-RSA which is now the
chosen cipher.

Signed-off-by: Sylvain Zimmer <sylvain@sylvainzimmer.com>
Signed-off-by: Damien George <damien@micropython.org>
2024-07-02 13:19:17 +10:00
Felix Dörre
57008a1e69 extmod/machine_usb_device: Add USBDevice.remote_wakeup method.
This simply exposes the TinyUSB function.

Signed-off-by: Felix Dörre <felix@dogcraft.de>
2024-07-02 10:23:26 +10:00
Alessandro Gatti
bb6a4669b2 py/asmrv32: Do not use binary literals.
As per discussion in #15347, non-standard binary literals have been
removed in favour of their hexadecimal counterparts.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-07-01 22:44:02 +02:00
Jim Mussared
557d31ed2c py/objint: Try to convert big-int back to small-int after binary op.
Before this change, long/mpz ints propagated into all future calculations,
even if their value could fit in a small-int object.  With this change, the
result of a big-int binary op will now be converted to a small-int object
if the value fits in a small-int.

For example, a relatively common operation like `x = a * b // c` where
a,b,c all small ints would always result in a long/mpz int, even if it
didn't need to, and then this would impact all future calculations with
x.

This adds +24 bytes on PYBV11 but avoids heap allocations and potential
surprises (e.g. `big-big` is now a small `0`, and can safely be accessed
with MP_OBJ_SMALL_INT_VALUE).

Performance tests are unchanged on PYBV10, except for `bm_pidigits.py`
which makes heavy use of big-ints and gains about 8% in speed.

Unix coverage tests have been updated to cover mpz code that is now
unreachable by normal Python code (removing the unreachable code would lead
to some surprising gaps in the internal C functions and the functionality
may be needed in the future, so it is kept because it has minimal
overhead).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2024-07-01 13:52:59 +10:00
Alessandro Gatti
0600e4f273 py/asmrv32: Make some code sequences smaller.
This commit changes a few code sequences to use more compressed opcodes
where possible.  The sequences in question are the ones that show up the
most in the test suite and require the least amount of code changes, namely
short offset loads from memory to RET/ARG registers, indirect calls through
the function table, register-based jumps, locals' offset calculation,
reg-is-null jumps, and register comparisons.

There are no speed losses or gains from these changes, but there is an
average 15-20% generated code size reduction.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-07-01 11:36:03 +10:00
Phil Howard
0e261443be rp2: Replace CMSIS funcs with Pico SDK equivalents.
Pico SDK defines `__dsb()` and `__sev()` so use those instead of the CMSIS
equivalents.  This matches the use of `__wfi()` in lieu of `__WFI()` and
lowers the dependency on CMSIS headers.

And then, move the include of "RP2040.h" from the widely-included
"mphalport.h" to specific source files that need this header, to keep its
inclusion contained.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-07-01 11:27:42 +10:00
Damien George
0dd25a369e rp2/boards/WEACTSTUDIO: Fix variant names in board.json.
It looks like the variants for this board were never being built properly,
because the auto-build system used the variant name from `board.json` which
did not match the variant names in the original `mpconfigboard.mk`.  Eg
`FLASH_2MB` in `board.json` but `FLASH_2M` in `mpconfigboard.mk`.

This mistake is apparent since 5dff78f38e,
which made it a build error to specify an invalid variant.

Fix this by using the correct variant names in `board.json`.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-28 22:48:46 +10:00
Damien George
95c19e05ff webassembly/objjsproxy: Lookup attributes without testing they exist.
In JavaScript when accessing an attribute such as `obj.attr` a value of
`undefined` is returned if the attribute does not exist.  This is unlike
Python semantics where an `AttributeError` is raised.  Furthermore, in some
cases in JavaScript (eg a Proxy instance) `attr in obj` can return false
yet `obj.attr` is still valid and returns something other than `undefined`.
So the source of truth for whether a JavaScript attribute exists is to just
right away attempt `obj.attr`.

To more closely match these JavaScript semantics when proxying a JavaScript
object through to Python, change the attribute lookup logic on a `JsProxy`
so that it immediately attempts `obj.attr` instead of first testing if the
attribute exists via `attr in obj`.

This allows JavaScript objects which dynamically create attributes to work
correctly on the Python side, with both `obj.attr` and `obj["attr"]`.  Note
that `obj["attr"]` already works in all cases because it immediately does
the subscript access without first testing if the attribute exists.

As a benefit, this new behaviour matches the Pyodide behaviour.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-28 11:40:24 +10:00
Damien George
5dff78f38e rp2: Rework board variant support to require mpconfigvariant file.
Following how the board variants now work in the esp32 port.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-28 11:25:07 +10:00
Damien George
81b1bfcfef stm32: Rework board variant support to require mpconfigvariant file.
Following how the board variants now work in the esp8266 port.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-28 11:24:46 +10:00
Damien George
daa948fe05 esp8266: Rework board variant support to require mpconfigvariant file.
Following how esp32 has been reworked, each variant now has a corresponding
`mpconfigvariant_VARIANT.mk` file associated with it.  The base variant
also has a `mpconfigvariant.mk` file because it has options that none of
the other variants use.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-28 11:24:08 +10:00
Damien George
43ebbec0c5 esp32: Rework board variant support to require mpconfigvariant file.
This commit reworks board variants on the esp32 port.  It's a simple change
that moves the board variant configuration from an "if" statement within
`mpconfigboard.cmake` into separate files for each variant, with the name
of the variant encoded in the filename: `mpconfigvariant_VARIANT.cmake`.

Optionally, the base variant can have its own options in
`mpconfigvariant.cmake` (this is an optional file, but all other variants
of the base must have a corresponding mpconfigvariant file).

There are two benefits to this:
- The build system now gives an error if the variant that you specified
  doesn't exist (because the mpconfigvariant file must exist with the
  variant name you specify).
- No more error-prone if-logic needed in the .cmake files.

The way to build a variant is unchanged, still via:

    $ make BOARD_VARIANT=VARIANT

Signed-off-by: Damien George <damien@micropython.org>
2024-06-28 11:23:55 +10:00
Jos Verlinde
3af1425be7 tools/mpremote: Fix mpremote mip install with multiple lib in sys.path.
This is a fix for an algorithmic error in mpremote mip, that throws an
error due to a '\n' used in the concatenation and split when there is more
than one lib path in `sys.path`.

Signed-off-by: Jos Verlinde <Jos.Verlinde@microsoft.com>
2024-06-28 11:07:01 +10:00
Yoctopuce
b4213c9c92 tools/mpy-tool.py: Implement freezing of long-long ints.
Allow inclusion of large integer constants in frozen files using long-long
representation (mpy-cross option -mlongint-impl=longlong).

Signed-off-by: Yoctopuce <dev@yoctopuce.com>
2024-06-27 17:53:31 +10:00
Damien George
706a4b4477 tools/ci.sh: Build an stm32 board with -O2 enabled.
To test building with full optimisations.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-27 12:00:20 +10:00
Damien George
096adca0c8 stm32/pin: Decrease machine_pin_obj_t.pin width from 5 to 4 bits.
Compiling using arm-none-eabi-gcc 14.1.0 with -O2 will give warnings about
possible overflow indexing extint arrays, such as `pyb_extint_callback`.
This is due to `machine_pin_obj_t.pin` having a bit-width of 5, and so a
possible value up to 31, which is usually larger than
`PYB_EXTI_NUM_VECTORS`.

To fix this, change `machine_pin_obj_t.pin` to a bit-width of 4.  Only 4
bits are needed for ST MCUs, which have up to 16 pins per port.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-27 12:00:20 +10:00
Damien George
74f52374e4 extmod/extmod.mk: Disable maybe-uninitialized warnings in libm_dbl.
These warnings are emitted by arm-none-eabi-gcc 14.1.0 with -O2 enabled.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-27 11:17:59 +10:00
Damien George
880f7bc040 shared/tinyusb/mp_usbd_cdc: Fix short CDC TX timeouts.
The `mp_event_wait_ms()` function may return earlier than the requested
timeout, and if that happens repeatedly (eg due to lots of USB data and
IRQs) then the loop waiting for CDC TX FIFO space to become available may
exit much earlier than MICROPY_HW_USB_CDC_TX_TIMEOUT, even when there is
no space.

Fix this by using `mp_hal_ticks_ms()` to compute a more accurate timeout.

The `basics/int_big_mul.py` test fails on RPI_PICO without this fix.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-26 14:50:42 +10:00
Angus Gratton
0c28a5ab06 github: Add Pull Request template.
Provides pull request submitters with contributor documentation, and
prompts them to provide relevant information about testing, and how they
came to implement this change.

Sections are deliberately small so they don't crowd out the GitHub Pull
Request description text field.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-26 14:47:13 +10:00
tharuka
206dc09456 README: Clean up a few bits of grammar.
The word "Select" could be confusing in this context, eg it could be
misunderstood as the `select` module.

Signed-off-by: tharuka <78165134+tharuka-pavith@users.noreply.github.com>
2024-06-26 14:40:39 +10:00
Yoctopuce
3d93fed0aa py/objarray: Fix buffer overflow in case of memory allocation failure.
If `array.append()` fails with an exception due to heap exhaustion, the
next attempt to grow the buffer will cause a buffer overflow because the
free slot count is increased before performing the allocation, and will
stay as if the allocation succeeded.

Signed-off-by: Yoctopuce <dev@yoctopuce.com>
2024-06-26 14:12:57 +10:00
Peter Harper
9111fa5831 shared/tinyusb/mp_usbd_runtime: Fix pointer comparison in assert.
Addresses build warning "comparison of distinct pointer types lacks a
cast".

Fixes issue #15276.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2024-06-26 13:57:45 +10:00
Peter Harper
e35f13a22d rp2/pendsv: Fix variable typo in assert so it compiles.
Fixes issue #15276.

Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
2024-06-26 13:57:39 +10:00
Angus Gratton
f60c71d131 rp2: Don't disable USB if going to DORMANT mode.
In this mode, XOSC is stopped so can't really keep
the USB PLL enabled.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-25 16:48:39 +10:00
Angus Gratton
068d9bf2cf rp2: Fix USB PLL glitch during wake from light sleep.
Follow-up to a84c7a0ed9, this commit works most of the time but has an
intermittent bug where USB doesn't resume as expected after waking from
light sleep.

Turns out waking calls clocks_init() which will re-initialise the USB PLL.
Most of the time this is OK but occasionally it seems like the clock
glitches the USB peripheral and it stops working until the next hard reset.

Adds a machine.lightsleep() test that consistently hangs in the first
two dozen iterations on rp2 without this fix. Passed over 100 times in a
row with this fix.

The test is currently rp2-only as it seems similar lightsleep USB issues
exist on other ports (both pyboard and ESP32-S3 native USB don't send any
data to the host after waking, until they receive something from the host
first.)

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-25 16:25:19 +10:00
Angus Gratton
5dcffb53ab rp2/clocks_extra: Implement custom clocks_init function.
Adapts pico-sdk clocks_init() into clocks_init_optional_usb() which takes
an argument to initialise USB clocks or not.

To avoid a code size increase the SDK clocks_init() function is linker
wrapped to become clocks_init_optional_usb(true).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-25 16:25:06 +10:00
Angus Gratton
cfa55b4ca1 rp2: Fix recursive atomic sections when core1 is active.
mp_thread_begin_atomic_section() is expected to be recursive (i.e. for
nested machine.disable_irq() calls, or if Python code calls disable_irq()
and then the Python runtime calls mp_handle_pending() which also enters an
atomic section to check the scheduler state).

On rp2 when not using core1 the atomic sections are recursive.

However when core1 was active (i.e. _thread) then there was a bug that
caused the core to live-lock if an atomic section recursed.

Adds a test case specifically for mutual exclusion and recursive atomic
sections when using two threads. Without this fix the test immediately
hangs on rp2.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-25 11:01:25 +10:00
Angus Gratton
908ab1ceca py/objint: Fix int.to_bytes() buffer size checks.
Fixes and improvements to `int.to_bytes()` are:
- No longer overflows if byte size is 0 (closes #13041).
- Raises OverflowError in any case where number won't fit into byte length
  (now matches CPython, previously MicroPython would return a truncated
  bytes object).
- Document that `micropython int.to_bytes()` doesn't implement the optional
  signed kwarg, but will behave as if `signed=True` when the integer is
  negative (this is the current behaviour).  Add tests for this also.

Requires changes for small ints, MPZ large ints, and "long long" large
ints.

Adds a new set of unit tests for ints between 32 and 64 bits to increase
coverage of "long long" large ints, which are otherwise untested.

Tested on unix port (64 bit small ints, MPZ long ints) and Zephyr STM32WB
board (32 bit small ints, long long large ints).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-24 14:07:00 +10:00
Angus Gratton
d933210d96 py/misc: Move mp_clz and mp_ctz intrinsics into misc.h.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-24 14:06:54 +10:00
Damien George
cebc9b0ae2 tools/mpremote: Fix absolute path usage in remote mounted VFS.
Prior to this fix the current working path in the remote VFS would always
be prepended to the requested path to get the full path, even if the
requested path was already absolute, ie starting with "/".

So `os.chdir("/remote/dir1")` would set the working path to "/dir1/", and
a subsequent call with an absolute path like `os.listdir("/remote/dir2")`
would try to list the directory "/dir1/dir2/".

Fixes issue #15308.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-21 16:46:49 +10:00
Damien George
0619f261a8 tests/basics: Add tests to test repeated throw into the same generator.
Signed-off-by: Damien George <damien@micropython.org>
2024-06-21 16:23:08 +10:00
Damien George
038125be79 py/emitnative: Fix native async with.
The code generating the entry to the finally handler of an async-with
statement was simply wrong for the case of the native emitter.  Among other
things the layout of the stack was incorrect.

This is fixed by this commit.  The setup of the async-with finally handler
is now put in a dedicated emit function, for both the bytecode and native
emitters to implement in their own way (the bytecode emitter is unchanged,
just factored to a function).

With this fix all of the async-with tests now work when using the native
emitter.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-21 16:21:33 +10:00
Damien George
a19214d897 py/emitnative: Place thrown value in dedicated local variable.
A value thrown/injected into a native generator needs to be stored in a
dedicated variable outside `nlr_buf_t`, following the `inject_exc` variable
in `py/vm.c`.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-21 16:21:29 +10:00
Damien George
9dbc787ce8 py/emitndebug: Add native debug emitter.
This emitter prints out pseudo-machine instructions, instead of the usual
output of the native emitter.  It can be enabled on any port via
`MICROPY_EMIT_NATIVE_DEBUG` (make sure other native emitters are disabled)
but the easiest way to use it is with mpy-cross:

    $ mpy-cross -march=debug file.py

Signed-off-by: Damien George <damien@micropython.org>
2024-06-21 16:21:27 +10:00
Damien George
e2ae03e979 py/emitnative: Add more DEBUG_printf statements.
Signed-off-by: Damien George <damien@micropython.org>
2024-06-21 16:06:02 +10:00
Alessandro Gatti
c1882e4866 qemu-riscv: Enable native code generation by default.
This turns on the native RV32IMC code generator for the QEMU-based
RISC-V port, and removes tests that relies on native code generation
from the exclusion list (ie enables these tests).

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-21 15:07:03 +10:00
Alessandro Gatti
3dd1130f6d py/emitnative: Emit better load/store sequences for RISC-V RV32IMC.
Selected load/store code sequences have been optimised for RV32IMC when the
chance to use fewer and smaller opcodes was possible.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-21 15:06:52 +10:00
Alessandro Gatti
99f5659cf5 mpy-cross: Add RISC-V RV32IMC support in MPY files.
MPY files can now hold generated RV32IMC native code.  This can be
accomplished by passing the `-march=rv32imc` flag to mpy-cross.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-21 15:06:29 +10:00
Alessandro Gatti
8338f66352 py/asmrv32: Add RISC-V RV32IMC native code emitter.
This adds a native code generation backend for RISC-V RV32I CPUs, currently
limited to the I, M, and C instruction sets.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-21 15:06:07 +10:00
Angus Gratton
5a778ebc37 tests/thread: Re-enable GC before stress_schedule test ends.
Otherwise GC stays disabled (not re-enabled by soft reset) and later test
runs fail with MemoryError.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-21 14:45:59 +10:00
Damien George
407464348d tests/cpydiff: Remove deque difference test.
Because `collections.deque` is now a built-in type in MicroPython.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-21 14:35:43 +10:00
Dan Halbert
5040b13dd4 py/objdeque: Fix deque type flags based on option settings.
This fixes a minor issue in the changes made by
7dff38fdc1: the type flags for deque were
meant to be conditionalized based on MICROPY_PY_COLLECTIONS_DEQUE_ITER, but
the computed conditionalized value wasn't used.

Signed-off-by: Dan Halbert <halbert@halwitz.org>
2024-06-21 14:27:33 +10:00
Damien George
88513d1226 webassembly/api: Allow specifying the pystack size.
This allows increasing the Python recursion depth if needed.

Also increase the default to 2k words.  There is enough RAM in the
browser/node context for this to be increased, and having a larger pystack
allows more complex code to run without hitting the limit.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-20 00:26:08 +10:00
Damien George
13195a678d webassembly/asyncio: Schedule run loop when tasks are pushed to queue.
In the webassembly port there is no asyncio run loop running at the top
level.  Instead the Python asyncio run loop is scheduled through setTimeout
and run by the outer JavaScript event loop.  Because tasks can become
runable from an external (to Python) event (eg a JavaScript callback), the
run loop must be scheduled whenever a task is pushed to the asyncio task
queue, otherwise tasks may be waiting forever on the queue.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-20 00:11:54 +10:00
Damien George
8ac9c8f392 extmod/modasyncio: Add support for a callback on TaskQueue push.
Allows passing in a callback to `TaskQueue()` that is called when something
is pushed on to the queue.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-20 00:11:05 +10:00
Damien George
e9c898cb33 webassembly/asyncio: Support top-level await of asyncio Task and Event.
This change allows doing a top-level await on an asyncio primitive like
Task and Event.

This feature enables a better interaction and synchronisation between
JavaScript and Python, because `api.runPythonAsync` can now be used (called
from JavaScript) to await on the completion of asyncio primitives.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-18 22:23:16 +10:00
Damien George
a053e63914 webassembly/objjsproxy: Implement proxying of JS iterable protocol.
This allows Python to iterate over JavaScript objects that provide
Symbol.iterator.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-18 22:14:34 +10:00
Maureen Helm
2b0e64beaf zephyr: Link MicroPython with the Zephyr kernel library.
Unlike most other Zephyr libraries, libkernel.a is not built as a
whole-archive.

This change also fixes a linker error observed on nucleo_wb55rg while
preparing an upgrade to Zephyr v3.5.0, caused by an undefined reference to
`z_impl_k_busy_wait`.

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
2024-06-18 16:19:07 +10:00
Jason Kridner
c211c05291 zephyr/modsocket: Add socket.recvfrom method.
Signed-off-by: Jason Kridner <jkridner@beagleboard.org>
2024-06-18 16:00:21 +10:00
Jason Kridner
0466560b12 zephyr/modzsensor: Add additional sensor type constants.
Signed-off-by: Jason Kridner <jkridner@beagleboard.org>
2024-06-18 15:54:25 +10:00
Alessandro Gatti
411d66586c extmod/modplatform: Add picolibc to the recognised libcs list.
This adds picolibc to the list of the recognised libc options.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-17 13:12:54 +10:00
Alessandro Gatti
1b10cb843c github/workflows: Add qemu-riscv port to CI.
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-17 12:06:09 +10:00
Alessandro Gatti
2d69aab7b3 qemu-riscv: Add new QEMU RV32 port.
This adds a QEMU-based bare metal RISC-V 32 bits port.  For the time being
only QEMU's "virt" 32 bits board is supported, using the ilp32 ABI and the
RV32IMC architecture.

The top-level README and the run-tests.py files are updated for this new
port.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-17 12:06:09 +10:00
Damien George
d7d77d91be qemu-arm: Clean up header file includes.
Signed-off-by: Damien George <damien@micropython.org>
2024-06-11 21:43:45 +10:00
Damien George
9bfb4cec6e qemu-arm: Add license and copyright to files missing them.
All of these files are first-party code written from scratch as part of
this repository, and were added when the top-level MIT license was active,
so they have an MIT license by default.  Tracing back the git history show
the original authors/source/copyright as follows:

- main.c, mpconfigport.h: copied from the bare-arm port [1].

- test_main.c: added in [2].

- mphalport.h: added in [3] then updated in [4].

- mps2.ld, nrf51.ld, stm32.ld, uart.h: added in [4].

- imx6.ld, uart.c, startup.c: added in [4] and updated in [5].

[1] Commit c557215822 in 2014, the initial
    bare-arm port; see related ee857853d6.
[2] Commit c1c32d65af in 2014, initial
    qemu-arm CI tests.
[3] Commit b0a15aa735 in 2016, enabling
    extmods and their tests.
[4] Commit e7332b0584 in 2018, big refactor.
[5] Commit b84406f313 in 2021, adding
    Cortex-A9 support.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-11 16:32:18 +10:00
Damien George
5903ee561c extmod/modlwip: Consolidate socket.accept timeout logic.
This makes the code a bit simpler to understand for the three cases of
timeout behaviour (-1, 0, non-zero), and eliminates a dependency on the
(slow) `mp_hal_delay_ms(100)` call.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-08 09:02:01 +10:00
Damien George
df0d7e9429 extmod/modlwip: Make socket.connect raise ETIMEDOUT on non-zero timeout.
If the socket timeout is 0 then a failed socket.connect() raises
EINPROGRESS (which is what the lwIP bindings already did), but if the
socket timeout is non-zero then a failed socket.connect() should raise
ETIMEDOUT.  The latter is fixed in this commit.

A test is added for these timeout cases.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-08 09:02:01 +10:00
Damien George
80a4f632ee rp2/cyw43_configport: Make cyw43_delay_ms() a busy loop.
Currently, `cyw43_delay_ms()` calls `mp_hal_delay_ms()` which uses PendSV
to set up a timer and wait for an interrupt, using wfe.  But in the cyw43
initialisation stage PendSV is disabled and so this delay suspends on the
wfe instruction for an indefinite amount of time.

Work around this by changing the implementation of `cyw43_delay_ms()` to a
busy loop.

Fixes issue #15220.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-08 08:43:49 +10:00
Damien George
3c8089d1b1 py/lexer: Support raw f-strings.
Support for raw str/bytes already exists, and extending that to raw
f-strings is easy.  It also reduces code size because it eliminates an
error message.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-06 17:34:28 +10:00
Damien George
a066f2308f py/lexer: Support concatenation of adjacent f-strings.
This is quite a simple and small change to support concatenation of
adjacent f-strings, and improve compatibility with CPython.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-06 14:58:46 +10:00
Alessandro Gatti
d7aa2fe9d7 lib/libm: Define _IEEE_LIBM only if not set.
fdilibm was originally meant to see _IEEE_LIBM defined from outside the
libm code, not it being hardcoded in.  Picolibc assumes this assumption
holds true and attempts to define itself, conflicting with the existing
definition.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-06 13:01:42 +10:00
Alessandro Gatti
ace08c3978 shared/runtime/semihosting: Add RISC-V semihosting support.
This adds a RISC-V RV32 semihosting implementation, with all defined
system calls exposed to the user.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-06 12:55:21 +10:00
Alessandro Gatti
90d50ce918 shared/runtime/semihosting: Rename ARM semihosting files.
Make room for RISC-V semihosting code, by renaming the existing
`semihosting.[ch]` files into `semihosting_arm.[ch]`.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-06 12:55:15 +10:00
Alessandro Gatti
de0e13a9a8 shared/runtime/gchelper: Add RISC-V RV32I native gchelper.
Add native gchelper support for 32 bits RISC-V RV32I targets.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-06 12:01:00 +10:00
Alessandro Gatti
e6ae699998 py/nlrrv32: Add RISC-V RV32I NLR implementation.
Add custom NLR support for 32 bits RISC-V RV32I targets.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-06 11:56:58 +10:00
Alessandro Gatti
596f92bf77 tools/makemanifest.py: Generate working code for empty manifests.
When no usable manifest directives are found (as opposed to no manifest
being set in the makefile), non-compiling code was generated for the
empty frozen constants pool block.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-06-05 14:07:26 +02:00
Andrew Leech
8809ae7161 shared/tinyusb: Buffer startup CDC data to send to host on connection.
At startup, buffer initial stdout / MicroyPthon banner so that it can be
sent to the host on initial connection of the USB serial port.  This
buffering also works for when the CDC becomes disconnected and the device
is still printing to stdout, and when CDC is reconnected the most recent
part of stdout (depending on how big the internal USB FIFO is) is flushed
to the host.

This change is most obvious when you've first plugged in a MicroPython
device (or hit reset), when it's a board that uses USB (CDC) serial in the
chip itself for the REPL interface.  This doesn't apply to UART going via a
separate USB-serial chip.

The stm32 port already has this buffering behaviour (it doesn't use
TinyUSB) and this commit extends such behaviour to rp2, mimxrt, samd and
renesas-ra ports, which do use TinyUSB.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-06-04 17:49:19 +10:00
Andrew Leech
d144f0699d lib/tinyusb: Update to the most recent master.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-06-04 17:47:51 +10:00
robert-hh
e138bafbc7 cc3200/mods: Implement network.ipconfig and network.WLAN.ipconfig.
Signed-off-by: robert-hh <robert@hammelrath.com>
2024-06-04 12:45:01 +10:00
Felix Dörre
9ece9f9b52 esp8266/network_wlan: Implement network.ipconfig and WLAN.ipconfig.
Co-authored-by: robert-hh <robert@hammelrath.com>

Signed-off-by: Felix Dörre <felix@dogcraft.de>
2024-06-04 12:45:01 +10:00
Felix Dörre
b555d6ccaf esp32/network_ppp: Implement network.PPP.ipconfig method.
Signed-off-by: Felix Dörre <felix@dogcraft.de>
2024-06-04 12:45:01 +10:00
robert-hh
a71471be66 extmod/network_lwip: Allow using the CIDR notation for addr4.
There was a little omisssion in the code.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-06-04 12:45:01 +10:00
robert-hh
7e7cc2b427 extmod/network_ninaw10: Implement the ipconfig methods for ninaw10.
This implements network.ipconfig() and network.WLAN.ipconfig() when the
ninaw10 driver is used for WLAN.

Due to a omission in the ninaw10 driver stack, setting the DNS address has
no effect.  But the interface is kept here just in case it's fixed
eventually.

dhcp4 and has_dhcp4 are dummy arguments.  Ninaw10 seems to always use DHCP.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-06-04 12:45:01 +10:00
Felix Dörre
1f23ab1e3d esp32,mimxrt,stm32: Implement ipconfig() for more network interfaces.
Implements:
- esp32: network.ipconfig()
- esp32: network.LAN.ipconfig()
- esp32: network.WLAN.ipconfig()
- mimxrt: network.LAN.ipconfig()
- stm32: network.LAN.ipconfig()

Signed-off-by: Felix Dörre <felix@dogcraft.de>
2024-06-04 12:45:01 +10:00
Damien George
0e19286c94 tools/metrics.py: Change rp2 board selection to RPI_PICO_W.
This tool is used to compute size differences in the firmware (eg as part
of CI), but it doesn't currently check any firmware that has bare-metal
lwIP/networking, making it hard to see how firmware size changes when
networking related changes are made.

So, change the board selection for the rp2 port to RPI_PICO_W.  Changes in
size to standard RPI_PICO firmware will be very similar to other bare-metal
boards like PYBV10.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-04 10:54:35 +10:00
Phil Howard
932f76c6ba rp2/CMakeLists: Use MICROPY_BOARD_DIR to find pins.csv.
Assuming that ${MICROPY_PORT_DIR}/boards/${MICROPY_BOARD} is equal to
${MICROPY_BOARD_DIR} is not valid, because the latter could point to a path
outside the main MicroPython repository.

Replace this path with the canonical ${MICROPY_BOARD_DIR} so that pins.csv
is correctly located when building against out-of-tree board definitions.

Additionally remove MICROPY_BOARDS_DIR to discourage similar mistakes.

Signed-off-by: Phil Howard <phil@gadgetoid.com>
2024-06-03 16:26:08 +10:00
Angus Gratton
a84c7a0ed9 rp2/modmachine: Selectively leave the USB clocks enabled in lightsleep.
Without this change going to lightsleep stops the USB peripheral clock, and
can lead to either the device going into a weird state or the host deciding
to issue a bus reset.

This change only keeps the USB peripheral clocks enabled if the USB device
is currently active and a host has configured the device.  This means the
USB device continues to respond to host transfers and (presumably) will
even complete pending endpoint transfers.  All other requests are NAKed
while still asleep, but the interaction with the host seems to resume
correctly on wake

Otherwise, if USB is not active or configured by a host, USB clocks are
disabled, the same as before.

With the change, one can issue a `machine.lightsleep(...)` with USB CDC
connected and the USB CDC remains connected during the sleep and resumes
when the lightsleep finishes.

Tested on a RPi Pico, the power consumption is:
- During normal idle at the REPL, about 15.3mA.
- During lightsleep, prior to this change, about 1.35mA.
- During lightsleep, with this change and USB CDC connected, about 3.7mA.

If power consumption should be as low as possible when USB is connected,
one can use `machine.USBDevice` to disable the USB before entering
lightsleep.

As discussed at https://github.com/orgs/micropython/discussions/14401

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-03 16:00:52 +10:00
93394da69c rp2/modmachine: Use atomic section macros in lightsleep code.
To avoid undefined references to `mp_thread_begin_atomic_section()` /
`mp_thread_end_atomic_section()`, replace them with the
`MICROPY_BEGIN_ATOMIC_SECTION` / `MICROPY_END_ATOMIC_SECTION`
macros.  That way, it's possible to build again with `MICROPY_PY_THREAD`
disabled (made possible by efa54c27b9).

Fixes commit 19844b4983.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2024-06-03 14:40:23 +10:00
Damien George
84a8f7ea6d shared/tinyusb: Allow ports to use 1200bps-touch without other CDC code.
This fixes the build for some esp32 and nrf boards (for example
`ARDUINO_NANO_33_BLE_SENSE` and `ARDUINO_NANO_ESP32`) due to commit
c98789a6d8.  Changes are:

- Allow the CDC TX/RX functions in `mp_usbd_cdc.c` to be enabled
  separately to those needed for `MICROPY_HW_USB_CDC_1200BPS_TOUCH`.

- Add `MICROPY_EXCLUDE_SHARED_TINYUSB_USBD_CDC` option as a temporary
  workaround for the nrf port to use.

- Declare `mp_usbd_line_state_cb()` in a header as a public function.

- Fix warning with type cast of `.callback_line_state_changed`.

Signed-off-by: Damien George <damien@micropython.org>
2024-06-02 23:27:33 +10:00
Angus Gratton
c1a6b95bf2 github/ISSUE_TEMPLATE: Update issue form to remove checklist generation.
Update to the issue forms added earlier this year, that seem to generally
be working well.  Improvements in this commit:

- No longer generates TODO checklists in new issues.

- Issue bodies (and therefore email previews) no longer start with the same
  fixed checklist text for each new issue.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-05-31 22:17:45 +10:00
Andrew Leech
c11efc74ee samd/mphalport: Refactor to use shared TinyUSB CDC functions.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-05-31 19:47:55 +10:00
Andrew Leech
2d33071b17 renesas-ra/mphalport: Refactor to use shared TinyUSB CDC functions.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-05-31 19:47:37 +10:00
Andrew Leech
2475a52f5c mimxrt/mphalport: Refactor to use shared TinyUSB CDC functions.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-05-31 19:47:25 +10:00
Andrew Leech
1eaa562fdf rp2/mphalport: Refactor to use shared TinyUSB CDC functions.
Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-05-31 19:47:05 +10:00
Andrew Leech
c98789a6d8 shared/tinyusb: Add common CDC TX/RX functions.
There are a few TinyUSB CDC functions used for stdio that are currently
replicated across a number of ports.  Not surprisingly in a couple of cases
these have started to diverge slightly, with additional features added to
one of them.

This commit consolidates a couple of key shared functions used directly by
TinyUSB based ports, and makes those functions available to all.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2024-05-31 19:45:42 +10:00
Alessandro Gatti
3613ad9624 lib/libm: Do not force floating point type size evaluation.
Since C99, `FLT_EVAL_METHOD` should be left for the compiler/libc to
define.  Its redefinition breaks compilation with picolibc as the
target's libc, since it defines said symbol in math.h before the libm
define is evaluated by the compiler.

In its place, there is a check to make sure floating point type sizes
are what are expected to be, triggering a compilation error if those
assumptions are no longer valid.

Co-authored-by: Angus Gratton <angus@redyak.com.au>
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2024-05-31 17:04:24 +10:00
Angus Gratton
3af006efb3 rp2: Support calling pendsv_suspend/resume from core 1.
Previously, this was subject to races incrementing/decrementing
the counter variable pendsv_lock.

Technically, all that's needed here would be to make pendsv_lock an atomic
counter.

This implementation fulfils a stronger guarantee: it also provides mutual
exclusion for the core which calls pendsv_suspend(). This is because the
current use of pendsv_suspend/resume in MicroPython is to ensure exclusive
access to softtimer data structures, and this does require mutual
exclusion.

The conceptually cleaner implementation would split the mutual exclusion
part out into a softtimer-specific spinlock, but this increases the
complexity and doesn't seem like it makes for a better implementation in
the long run.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-05-31 16:46:27 +10:00
Angus Gratton
83e82c5ad3 rp2: Refactor to not use pico-sdk alarm pool functions for sleeping.
The best_effort_wfe_or_timeout() and sleep_us() pico-sdk functions use the
pico-sdk alarm pool internally, and that has a bug.

Some usages inside pico-sdk (notably multicore_lockout_start_blocking())
will still end up calling best_effort_wfe_or_timeout(), although usually
with "end_of_time" as the timeout value so it should avoid any alarm pool
race conditions.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-05-31 16:44:09 +10:00
Angus Gratton
74fb42aa82 rp2: Refactor soft timer to use hardware timer alarm.
Progress towards removing pico-sdk alarm pool, due to a known issue.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-05-31 16:43:52 +10:00
Damien George
2926001b60 all: Bump version to 1.24.0-preview.
Signed-off-by: Damien George <damien@micropython.org>
2024-05-31 16:35:27 +10:00
877 changed files with 25104 additions and 5482 deletions

View File

@@ -11,19 +11,10 @@ body:
* If you have a question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here. * If you have a question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
* For missing or incorrect documentation, or feature requests, then please [choose a different issue type](https://github.com/micropython/micropython/issues/new/choose). * For missing or incorrect documentation, or feature requests, then please [choose a different issue type](https://github.com/micropython/micropython/issues/new/choose).
- type: checkboxes
id: terms #### Existing issue?
attributes:
label: Checks * Please search for [existing issues](https://github.com/micropython/micropython/issues) matching this bug before reporting.
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) matching this bug, and didn't find any.
required: true
- type: input - type: input
id: port-board-hw id: port-board-hw
attributes: attributes:
@@ -33,7 +24,7 @@ body:
placeholder: | placeholder: |
esp32 port, ESP32-Fantastic board. esp32 port, ESP32-Fantastic board.
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: version id: version
attributes: attributes:
@@ -101,6 +92,17 @@ body:
description: | description: |
Is there anything else that might help to resolve this issue? Is there anything else that might help to resolve this issue?
value: No, I've provided everything above. value: No, I've provided everything above.
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true
- type: markdown - type: markdown
attributes: attributes:
value: | value: |

View File

@@ -9,19 +9,10 @@ body:
This form is for reporting issues with the documentation or examples provided with MicroPython. This form is for reporting issues with the documentation or examples provided with MicroPython.
If you have a general question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here. If you have a general question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
- type: checkboxes
id: terms #### Existing issue?
attributes:
label: Checks * Please search for [existing issues](https://github.com/micropython/micropython/issues) before reporting a new one.
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) and didn't find any that matched.
required: true
- type: input - type: input
id: page id: page
attributes: attributes:
@@ -38,6 +29,17 @@ body:
Please describe what was missing from the documentation and/or what was incorrect/incomplete. Please describe what was missing from the documentation and/or what was incorrect/incomplete.
validations: validations:
required: true required: true
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true
- type: markdown - type: markdown
attributes: attributes:
value: | value: |

View File

@@ -15,19 +15,10 @@ body:
* If you have a question \"How Do I ...?\", please post it on GitHub Discussions or Discord instead of here. * If you have a question \"How Do I ...?\", please post it on GitHub Discussions or Discord instead of here.
* Could this feature be implemented as a pure Python library? If so, please open the request on the [micropython-lib repository](https://github.com/micropython/micropython-lib/issues) instead. * Could this feature be implemented as a pure Python library? If so, please open the request on the [micropython-lib repository](https://github.com/micropython/micropython-lib/issues) instead.
- type: checkboxes
id: terms #### Existing issue?
attributes:
label: Checks * Please search for [existing issues](https://github.com/micropython/micropython/issues) before opening a new one.
description: |
Before submitting your feature request, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) regarding this feature, and didn't find any.
required: true
- type: textarea - type: textarea
id: feature id: feature
attributes: attributes:
@@ -51,14 +42,32 @@ body:
MicroPython aims to strike a balance between functionality and code size. Can this feature be optionally enabled? MicroPython aims to strike a balance between functionality and code size. Can this feature be optionally enabled?
If you believe the usefulness of this feature would outweigh the additional code size, please explain. (It's OK to say you're unsure here, we're happy to discuss this with you.) If you believe the usefulness of this feature would outweigh the additional code size, please explain. (It's OK to say you're unsure here, we're happy to discuss this with you.)
- type: checkboxes - type: dropdown
id: implementation id: implementation
attributes: attributes:
label: Implementation label: Implementation
description: |
What is your suggestion for implementing this feature?
(See also: [How to sponsor](https://github.com/sponsors/micropython#sponsors), [How to submit a Pull Request](https://github.com/micropython/micropython/wiki/ContributorGuidelines).)
options: options:
- label: I intend to implement this feature and would submit a Pull Request if desirable. - I hope the MicroPython maintainers or community will implement this feature
- label: I hope the MicroPython maintainers or community will implement this feature. - I intend to implement this feature and would submit a Pull Request if desirable
- label: I would like to [Sponsor](https://github.com/sponsors/micropython#sponsors) development of this feature. - I would like to sponsor development of this feature
multiple: true
validations:
required: true
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true
- type: markdown - type: markdown
attributes: attributes:
value: | value: |

View File

@@ -9,21 +9,11 @@ body:
1. For issues that are readily exploitable or have high impact, please email contact@micropython.org instead. 1. For issues that are readily exploitable or have high impact, please email contact@micropython.org instead.
1. If this is a question about security, please ask it in [Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead. 1. If this is a question about security, please ask it in [Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead.
- type: checkboxes
id: terms #### Existing issue?
attributes:
label: Checks * Please search for [existing issues](https://github.com/micropython/micropython/issues) before reporting a new one.
description: |
Before submitting your bug report, please go over these check points:
options:
- label: |
I agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone.
required: true
- label: I wish to report a specific security issue that is **not readily exploitable and does not have high impact** for MicroPython developers or users.
required: true
- label: |
I've searched for [existing issues](https://github.com/micropython/micropython/issues) and didn't find any that matched.
required: true
- type: input - type: input
id: port-board-hw id: port-board-hw
attributes: attributes:
@@ -57,3 +47,14 @@ body:
* How does the attacker exploit this issue? * How does the attacker exploit this issue?
validations: validations:
required: true required: true
- type: dropdown
id: code-of-conduct
attributes:
label: Code of Conduct
description: |
Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
options:
- "Yes, I agree"
multiple: true
validations:
required: true

33
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,33 @@
<!-- Thanks for submitting a Pull Request! We appreciate you spending the
time to improve MicroPython. Please provide enough information so that
others can review your Pull Request.
Before submitting, please read:
https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md
https://github.com/micropython/micropython/wiki/ContributorGuidelines
Please check any CI failures that appear after your Pull Request is opened.
-->
### Summary
<!-- Explain the reason for making this change. What problem does the pull request
solve, or what improvement does it add? Add links if relevant. -->
### Testing
<!-- Explain what testing you did, and on which boards/ports. If there are
boards or ports that you couldn't test, please mention this here as well.
If you leave this empty then your Pull Request may be closed. -->
### Trade-offs and Alternatives
<!-- If the Pull Request has some negative impact (i.e. increased code size)
then please explain why you think the trade-off improvement is worth it.
If you can think of alternative ways to do this, please explain that here too.
Delete this heading if not relevant (i.e. small fixes) -->

View File

@@ -24,7 +24,7 @@ concurrency:
jobs: jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

View File

@@ -11,7 +11,7 @@ concurrency:
jobs: jobs:
comment: comment:
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: 'Download artifact' - name: 'Download artifact'
id: download-artifact id: download-artifact

View File

@@ -1,32 +0,0 @@
name: qemu-arm port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/qemu-arm/**'
- 'tests/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_qemu_arm_setup
- name: Build and run test suite
run: source tools/ci.sh && ci_qemu_arm_build
- name: Print failures
if: failure()
run: grep --before-context=100 --text "FAIL" ports/qemu-arm/build/console.out

44
.github/workflows/ports_qemu.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
name: qemu port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/qemu/**'
- 'tests/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_and_test_arm:
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: Print failures
if: failure()
run: tests/run-tests.py --print-failures
build_and_test_rv32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_qemu_setup_rv32
- name: Build and run test suite
run: source tools/ci.sh && ci_qemu_build_rv32
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@@ -194,7 +194,7 @@ jobs:
run: tests/run-tests.py --print-failures run: tests/run-tests.py --print-failures
macos: macos:
runs-on: macos-11.0 runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
@@ -235,3 +235,17 @@ jobs:
- name: Print failures - name: Print failures
if: failure() if: failure()
run: tests/run-tests.py --print-failures run: tests/run-tests.py --print-failures
qemu_riscv64:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_unix_qemu_riscv64_setup
- name: Build
run: source tools/ci.sh && ci_unix_qemu_riscv64_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_qemu_riscv64_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

View File

@@ -42,6 +42,8 @@ jobs:
configuration: Debug configuration: Debug
- visualstudio: '2019' - visualstudio: '2019'
configuration: Debug configuration: Debug
env:
CI_BUILD_CONFIGURATION: ${{ matrix.configuration }}
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
steps: steps:
- name: Install Visual Studio 2017 - name: Install Visual Studio 2017
@@ -108,16 +110,6 @@ jobs:
run: run:
shell: msys2 {0} shell: msys2 {0}
steps: steps:
- name: Get Python path
id: python_path
shell: python
run: |
import os
import sys
output = f"python={os.fspath(sys.executable)}"
print(output)
with open(os.environ["GITHUB_OUTPUT"], "w") as f:
f.write(output)
- uses: msys2/setup-msys2@v2 - uses: msys2/setup-msys2@v2
with: with:
msystem: ${{ matrix.sys }} msystem: ${{ matrix.sys }}
@@ -126,7 +118,7 @@ jobs:
make make
mingw-w64-${{ matrix.env }}-gcc mingw-w64-${{ matrix.env }}-gcc
pkg-config pkg-config
python3 mingw-w64-${{ matrix.env }}-python3
git git
diffutils diffutils
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -138,8 +130,7 @@ jobs:
run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }} run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }}
- name: Run tests - name: Run tests
id: test id: test
# msys python breaks tests so we need to use "real" windows python run: make -C ports/windows test_full VARIANT=${{ matrix.variant }}
run: MICROPY_CPYTHON3=$(cygpath "${{ steps.python_path.outputs.python }}") make -C ports/windows test_full VARIANT=${{ matrix.variant }}
- name: Print failures - name: Print failures
if: failure() && steps.test.conclusion == 'failure' if: failure() && steps.test.conclusion == 'failure'
working-directory: tests working-directory: tests

View File

@@ -20,6 +20,15 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: jlumbroso/free-disk-space@main
with:
# Only free up a few things so this step runs quickly.
android: false
dotnet: true
haskell: true
large-packages: false
docker-images: false
swap-storage: false
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install packages - name: Install packages
run: source tools/ci.sh && ci_zephyr_setup run: source tools/ci.sh && ci_zephyr_setup
@@ -27,3 +36,8 @@ jobs:
run: source tools/ci.sh && ci_zephyr_install run: source tools/ci.sh && ci_zephyr_install
- name: Build - name: Build
run: source tools/ci.sh && ci_zephyr_build run: source tools/ci.sh && ci_zephyr_build
- name: Run main test suite
run: source tools/ci.sh && ci_zephyr_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

3
.gitignore vendored
View File

@@ -11,8 +11,9 @@ build/
build-*/ build-*/
docs/genrst/ docs/genrst/
# Test failure outputs # Test failure outputs and intermediate artefacts
tests/results/* tests/results/*
tests/ports/unix/ffi_lib.so
# Python cache files # Python cache files
__pycache__/ __pycache__/

2
.gitmodules vendored
View File

@@ -3,7 +3,7 @@
url = https://github.com/micropython/axtls.git url = https://github.com/micropython/axtls.git
[submodule "lib/libffi"] [submodule "lib/libffi"]
path = lib/libffi path = lib/libffi
url = https://github.com/atgreen/libffi url = https://github.com/libffi/libffi
[submodule "lib/lwip"] [submodule "lib/lwip"]
path = lib/lwip path = lib/lwip
url = https://github.com/lwip-tcpip/lwip.git url = https://github.com/lwip-tcpip/lwip.git

View File

@@ -59,7 +59,6 @@ used during the build process and is not part of the compiled source code.
/pico-sdk (BSD-3-clause) /pico-sdk (BSD-3-clause)
/re15 (BSD-3-clause) /re15 (BSD-3-clause)
/stm32lib (BSD-3-clause) /stm32lib (BSD-3-clause)
/tinytest (BSD-3-clause)
/tinyusb (MIT) /tinyusb (MIT)
/uzlib (Zlib) /uzlib (Zlib)
/wiznet5k (MIT) /wiznet5k (MIT)
@@ -73,6 +72,7 @@ used during the build process and is not part of the compiled source code.
/ppp_set_auth.* (Apache-2.0) /ppp_set_auth.* (Apache-2.0)
/rp2 /rp2
/mutex_extra.c (BSD-3-clause) /mutex_extra.c (BSD-3-clause)
/clocks_extra.c (BSD-3-clause)
/stm32 /stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2) /usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause) /stm32_it.* (MIT + BSD-3-clause)

View File

@@ -19,7 +19,7 @@ Python 3.5 and some select features from later versions). The following core
datatypes are provided: `str`(including basic Unicode support), `bytes`, datatypes are provided: `str`(including basic Unicode support), `bytes`,
`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`, `bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`,
`collections.namedtuple`, classes and instances. Builtin modules include `collections.namedtuple`, classes and instances. Builtin modules include
`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for `os`, `sys`, `time`, `re`, and `struct`, etc. Some ports have support for
`_thread` module (multithreading), `socket` and `ssl` for networking, and `_thread` module (multithreading), `socket` and `ssl` for networking, and
`asyncio`. Note that only a subset of Python 3 functionality is implemented `asyncio`. Note that only a subset of Python 3 functionality is implemented
for the data types and modules. for the data types and modules.
@@ -35,8 +35,8 @@ DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
Getting started Getting started
--------------- ---------------
See the [online documentation](https://docs.micropython.org/) for API See the [online documentation](https://docs.micropython.org/) for the API
references and information about using MicroPython and information about how reference and information about using MicroPython and information about how
it is implemented. it is implemented.
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions) We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
@@ -108,13 +108,13 @@ track of the code size of the core runtime and VM.
In addition, the following ports are provided in this repository: In addition, the following ports are provided in this repository:
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy). - [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3). - [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3, ESP32C6).
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC. - [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x). - [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52. - [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit. - [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt) - [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
- [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing) - [qemu](ports/qemu) -- QEMU-based emulated target (for testing)
- [renesas-ra](ports/renesas-ra) -- Renesas RA family. - [renesas-ra](ports/renesas-ra) -- Renesas RA family.
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W). - [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51. - [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.

View File

@@ -59,7 +59,7 @@ A MicroPython user C module is a directory with the following files:
SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c
Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++ Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++
source files. source files. If you want to include assembly files use ``SRC_USERMOD_LIB_ASM``.
If you have custom compiler options (like ``-I`` to add directories to search If you have custom compiler options (like ``-I`` to add directories to search
for header files), these should be added to ``CFLAGS_USERMOD`` for C code for header files), these should be added to ``CFLAGS_USERMOD`` for C code

View File

@@ -18,7 +18,7 @@ working with this board it may be useful to get an overview of the microcontroll
general.rst general.rst
tutorial/index.rst tutorial/index.rst
Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32S2, ESP32S3 -- Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32C6, ESP32S2, ESP32S3 --
supported by MicroPython, with some differences in functionality between them. supported by MicroPython, with some differences in functionality between them.
Installing MicroPython Installing MicroPython
@@ -61,13 +61,13 @@ The :mod:`esp32` module::
import esp32 import esp32
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3 esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3/C6
Note that the temperature sensor in the ESP32 will typically read higher than Note that the temperature sensor in the ESP32 will typically read higher than
ambient due to the IC getting warm while it runs. This effect can be minimised ambient due to the IC getting warm while it runs. This effect can be minimised
by reading the temperature sensor immediately after waking up from sleep. by reading the temperature sensor immediately after waking up from sleep.
ESP32C3, ESP32S2, and ESP32S3 also have an internal temperature sensor available. ESP32C3, ESP32C6, ESP32S2, and ESP32S3 also have an internal temperature sensor available.
It is implemented a bit differently to the ESP32 and returns the temperature in It is implemented a bit differently to the ESP32 and returns the temperature in
Celsius:: Celsius::
@@ -89,7 +89,7 @@ The :mod:`network` module::
wlan.isconnected() # check if the station is connected to an AP wlan.isconnected() # check if the station is connected to an AP
wlan.connect('ssid', 'key') # connect to an AP wlan.connect('ssid', 'key') # connect to an AP
wlan.config('mac') # get the interface's MAC address wlan.config('mac') # get the interface's MAC address
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses wlan.ipconfig('addr4') # get the interface's IPv4 addresses
ap = network.WLAN(network.AP_IF) # create access-point interface ap = network.WLAN(network.AP_IF) # create access-point interface
ap.config(ssid='ESP-AP') # set the SSID of the access point ap.config(ssid='ESP-AP') # set the SSID of the access point
@@ -107,7 +107,7 @@ A useful function for connecting to your local WiFi network is::
wlan.connect('ssid', 'key') wlan.connect('ssid', 'key')
while not wlan.isconnected(): while not wlan.isconnected():
pass pass
print('network config:', wlan.ifconfig()) print('network config:', wlan.ipconfig('addr4'))
Once the network is established the :mod:`socket <socket>` module can be used Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual, and the ``requests`` module for to create and use TCP/UDP sockets as usual, and the ``requests`` module for
@@ -130,7 +130,7 @@ To use the wired interfaces one has to specify the pins and mode ::
lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration
lan.active(True) # activate the interface lan.active(True) # activate the interface
lan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses lan.ipconfig('addr4') # get the interface's IPv4 addresses
The keyword arguments for the constructor defining the PHY type and interface are: The keyword arguments for the constructor defining the PHY type and interface are:

View File

@@ -32,6 +32,18 @@ the prescaler of the MCPWM0 peripheral.
mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG
The specific addresses will be different on different ESP32
models. For example, ESP32-S3 uses these values:
.. code-block:: python3
DR_REG_DPORT_BASE = const(0x600C_0000)
DPORT_PERIP_CLK_EN0_REG = const(DR_REG_DPORT_BASE + 0x0018)
DPORT_PERIP_RST_EN0_REG = const(DR_REG_DPORT_BASE + 0x0020)
DPORT_PWM0_CLK_EN = const(1 << 17)
MCPWM0 = const(0x6001_E000 + 0x0004)
...
Note that before a peripheral can be used its clock must be enabled and it must Note that before a peripheral can be used its clock must be enabled and it must
be taken out of reset. In the above example the following registers are used be taken out of reset. In the above example the following registers are used
for this: for this:

View File

@@ -59,7 +59,7 @@ The :mod:`network` module::
wlan.isconnected() # check if the station is connected to an AP wlan.isconnected() # check if the station is connected to an AP
wlan.connect('ssid', 'key') # connect to an AP wlan.connect('ssid', 'key') # connect to an AP
wlan.config('mac') # get the interface's MAC address wlan.config('mac') # get the interface's MAC address
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses wlan.ipconfig('addr4') # get the interface's IPv4 addresses
ap = network.WLAN(network.AP_IF) # create access-point interface ap = network.WLAN(network.AP_IF) # create access-point interface
ap.active(True) # activate the interface ap.active(True) # activate the interface
@@ -76,7 +76,7 @@ A useful function for connecting to your local WiFi network is::
wlan.connect('ssid', 'key') wlan.connect('ssid', 'key')
while not wlan.isconnected(): while not wlan.isconnected():
pass pass
print('network config:', wlan.ifconfig()) print('network config:', wlan.ipconfig('addr4'))
Once the network is established the :mod:`socket <socket>` module can be used Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual. to create and use TCP/UDP sockets as usual.

View File

@@ -19,10 +19,10 @@ You can check if the interfaces are active by::
You can also check the network settings of the interface by:: You can also check the network settings of the interface by::
>>> ap_if.ifconfig() >>> ap_if.ipconfig('addr4')
('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8') ('192.168.4.1', '255.255.255.0')
The returned values are: IP address, netmask, gateway, DNS. The returned values are: IP address and netmask.
Configuration of the WiFi Configuration of the WiFi
------------------------- -------------------------
@@ -45,8 +45,8 @@ To check if the connection is established use::
Once established you can check the IP address:: Once established you can check the IP address::
>>> sta_if.ifconfig() >>> sta_if.ipconfig('addr4')
('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8') ('192.168.0.2', '255.255.255.0')
You can then disable the access-point interface if you no longer need it:: You can then disable the access-point interface if you no longer need it::
@@ -64,7 +64,7 @@ connect to your WiFi network::
sta_if.connect('<ssid>', '<key>') sta_if.connect('<ssid>', '<key>')
while not sta_if.isconnected(): while not sta_if.isconnected():
pass pass
print('network config:', sta_if.ifconfig()) print('network config:', sta_if.ipconfig('addr4'))
Sockets Sockets
------- -------

View File

@@ -82,6 +82,10 @@ Functions and types
In MicroPython, `byteorder` parameter must be positional (this is In MicroPython, `byteorder` parameter must be positional (this is
compatible with CPython). compatible with CPython).
.. note:: The optional ``signed`` kwarg from CPython is not supported.
MicroPython currently converts negative integers as signed,
and positive as unsigned. (:ref:`Details <cpydiff_types_int_to_bytes>`.)
.. function:: isinstance() .. function:: isinstance()
.. function:: issubclass() .. function:: issubclass()

View File

@@ -238,6 +238,12 @@ The following methods are not part of the core Pin API and only implemented on c
Availability: cc3200 port. Availability: cc3200 port.
.. method:: Pin.toggle()
Toggle output pin from "0" to "1" or vice-versa.
Availability: mimxrt, samd, rp2 ports.
Constants Constants
--------- ---------

View File

@@ -152,31 +152,6 @@ Methods
Send a break condition on the bus. This drives the bus low for a duration Send a break condition on the bus. This drives the bus low for a duration
longer than required for a normal transmission of a character. longer than required for a normal transmission of a character.
.. method:: UART.irq(trigger, priority=1, handler=None, wake=machine.IDLE)
Create a callback to be triggered when data is received on the UART.
- *trigger* can only be ``UART.RX_ANY``
- *priority* level of the interrupt. Can take values in the range 1-7.
Higher values represent higher priorities.
- *handler* an optional function to be called when new characters arrive.
- *wake* can only be ``machine.IDLE``.
.. note::
The handler will be called whenever any of the following two conditions are met:
- 8 new characters have been received.
- At least 1 new character is waiting in the Rx buffer and the Rx line has been
silent for the duration of 1 complete frame.
This means that when the handler function is called there will be between 1 to 8
characters waiting.
Returns an irq object.
Availability: WiPy.
.. method:: UART.flush() .. method:: UART.flush()
Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout
@@ -185,7 +160,7 @@ Methods
.. note:: .. note::
For the rp2, esp8266 and nrf ports the call returns while the last byte is sent. For the esp8266 and nrf ports the call returns while the last byte is sent.
If required, a one character wait time has to be added in the calling script. If required, a one character wait time has to be added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
@@ -197,17 +172,91 @@ Methods
.. note:: .. note::
For the rp2, esp8266 and nrf ports the call may return ``True`` even if the last byte For the esp8266 and nrf ports the call may return ``True`` even if the last byte
of a transfer is still being sent. If required, a one character wait time has to be of a transfer is still being sent. If required, a one character wait time has to be
added in the calling script. added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
.. method:: UART.irq(handler=None, trigger=0, hard=False)
Configure an interrupt handler to be called when a UART event occurs.
The arguments are:
- *handler* is an optional function to be called when the interrupt event
triggers. The handler must take exactly one argument which is the
``UART`` instance.
- *trigger* configures the event(s) which can generate an interrupt.
Possible values are a mask of one or more of the following:
- ``UART.IRQ_RXIDLE`` interrupt after receiving at least one character
and then the RX line goes idle.
- ``UART.IRQ_RX`` interrupt after each received character.
- ``UART.IRQ_TXIDLE`` interrupt after or while the last character(s) of
a message are or have been sent.
- ``UART.IRQ_BREAK`` interrupt when a break state is detected at RX
- *hard* if true a hardware interrupt is used. This reduces the delay
between the pin change and the handler being called. Hard interrupt
handlers may not allocate memory; see :ref:`isr_rules`.
Returns an irq object.
Due to limitations of the hardware not all trigger events are available on all ports.
.. table:: Availability of triggers
:align: center
============== ========== ====== ========== =========
Port / Trigger IRQ_RXIDLE IRQ_RX IRQ_TXIDLE IRQ_BREAK
============== ========== ====== ========== =========
CC3200 yes
ESP32 yes yes yes
MIMXRT yes yes
NRF yes yes
RENESAS-RA yes yes
RP2 yes yes yes
SAMD yes yes yes
STM32 yes yes
============== ========== ====== ========== =========
.. note::
- The ESP32 port does not support the option hard=True.
- 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
are to be sent.
- The rp2 port's UART.IRQ_BREAK needs receiving valid characters for triggering
again.
- The SAMD port's UART.IRQ_TXIDLE is triggered while the last character is sent.
- On STM32F4xx MCU's, using the trigger UART.IRQ_RXIDLE the handler will be called once
after the first character and then after the end of the message, when the line is
idle.
Availability: cc3200, esp32, mimxrt, nrf, renesas-ra, rp2, samd, stm32.
Constants Constants
--------- ---------
.. data:: UART.RX_ANY .. data:: UART.RTS
UART.CTS
IRQ trigger sources Flow control options.
Availability: WiPy. Availability: esp32, mimxrt, renesas-ra, rp2, stm32.
.. data:: UART.IRQ_RXIDLE
UART.IRQ_RX
UART.IRQ_TXIDLE
UART.IRQ_BREAK
IRQ trigger sources.
Availability: renesas-ra, stm32, esp32, rp2040, mimxrt, samd, cc3200.

View File

@@ -215,6 +215,13 @@ Methods
drivers. Placing a different string at any of these indexes overrides that drivers. Placing a different string at any of these indexes overrides that
string in the built-in driver. string in the built-in driver.
.. method:: USBDevice.remote_wakeup(self)
Wake up host if we are in suspend mode and the REMOTE_WAKEUP feature
is enabled by the host. This has to be enabled in the USB attributes,
and on the host. Returns ``True`` if remote wakeup was enabled and
active and the host was woken up.
.. method:: USBDevice.submit_xfer(self, ep, buffer /) .. method:: USBDevice.submit_xfer(self, ep, buffer /)
Submit a USB transfer on endpoint number ``ep``. ``buffer`` must be Submit a USB transfer on endpoint number ``ep``. ``buffer`` must be

View File

@@ -127,14 +127,20 @@ Power related functions
.. function:: idle() .. function:: idle()
Gates the clock to the CPU, useful to reduce power consumption at any time during Gates the clock to the CPU, useful to reduce power consumption at any time
short or long periods. Peripherals continue working and execution resumes as soon during short or long periods. Peripherals continue working and execution
as any interrupt is triggered (on many ports this includes system timer resumes as soon as any interrupt is triggered, or at most one millisecond
interrupt occurring at regular intervals on the order of millisecond). after the CPU was paused.
It is recommended to call this function inside any tight loop that is
continuously checking for an external change (i.e. polling). This will reduce
power consumption without significantly impacting performance. To reduce
power consumption further then see the :func:`lightsleep`,
:func:`time.sleep()` and :func:`time.sleep_ms()` functions.
.. function:: sleep() .. function:: sleep()
.. note:: This function is deprecated, use `lightsleep()` instead with no arguments. .. note:: This function is deprecated, use :func:`lightsleep()` instead with no arguments.
.. function:: lightsleep([time_ms]) .. function:: lightsleep([time_ms])
deepsleep([time_ms]) deepsleep([time_ms])

View File

@@ -125,8 +125,11 @@ Functions
Return the natural logarithm of the gamma function of ``x``. Return the natural logarithm of the gamma function of ``x``.
.. function:: log(x) .. function:: log(x)
log(x, base)
Return the natural logarithm of ``x``. With one argument, return the natural logarithm of *x*.
With two arguments, return the logarithm of *x* to the given *base*.
.. function:: log10(x) .. function:: log10(x)

View File

@@ -136,6 +136,14 @@ Functions
the heap may be locked) and scheduling a function to call later will lift the heap may be locked) and scheduling a function to call later will lift
those restrictions. those restrictions.
On multi-threaded ports, the scheduled function's behaviour depends on
whether the Global Interpreter Lock (GIL) is enabled for the specific port:
- If GIL is enabled, the function can preempt any thread and run in its
context.
- If GIL is disabled, the function will only preempt the main thread and run
in its context.
Note: If `schedule()` is called from a preempting IRQ, when memory Note: If `schedule()` is called from a preempting IRQ, when memory
allocation is not allowed and the callback to be passed to `schedule()` is allocation is not allowed and the callback to be passed to `schedule()` is
a bound method, passing this directly will fail. This is because creating a a bound method, passing this directly will fail. This is because creating a
@@ -147,3 +155,71 @@ Functions
There is a finite queue to hold the scheduled functions and `schedule()` There is a finite queue to hold the scheduled functions and `schedule()`
will raise a `RuntimeError` if the queue is full. will raise a `RuntimeError` if the queue is full.
Classes
-------
.. class:: RingIO(size)
.. class:: RingIO(buffer)
:noindex:
Provides a fixed-size ringbuffer for bytes with a stream interface. Can be
considered like a fifo queue variant of `io.BytesIO`.
When created with integer size a suitable buffer will be allocated.
Alternatively a `bytearray` or similar buffer protocol object can be provided
to the constructor for in-place use.
The classic ringbuffer algorithm is used which allows for any size buffer
to be used however one byte will be consumed for tracking. If initialised
with an integer size this will be accounted for, for example ``RingIO(16)``
will allocate a 17 byte buffer internally so it can hold 16 bytes of data.
When passing in a pre-allocated buffer however one byte less than its
original length will be available for storage, eg. ``RingIO(bytearray(16))``
will only hold 15 bytes of data.
A RingIO instance can be IRQ / thread safe when used to pass data in a single
direction eg. when written to in an IRQ and read from in a non-IRQ function
(or vice versa). This does not hold if you try to eg. write to a single instance
from both IRQ and non-IRQ code, this would often cause data corruption.
.. method:: RingIO.any()
Returns an integer counting the number of characters that can be read.
.. method:: RingIO.read([nbytes])
Read available characters. This is a non-blocking function. If ``nbytes``
is specified then read at most that many bytes, otherwise read as much
data as possible.
Return value: a bytes object containing the bytes read. Will be
zero-length bytes object if no data is available.
.. method:: RingIO.readline([nbytes])
Read a line, ending in a newline character or return if one exists in
the buffer, else return available bytes in buffer. If ``nbytes`` is
specified then read at most that many bytes.
Return value: a bytes object containing the line read.
.. method:: RingIO.readinto(buf[, nbytes])
Read available bytes into the provided ``buf``. If ``nbytes`` is
specified then read at most that many bytes. Otherwise, read at
most ``len(buf)`` bytes.
Return value: Integer count of the number of bytes read into ``buf``.
.. method:: RingIO.write(buf)
Non-blocking write of bytes from ``buf`` into the ringbuffer, limited
by the available space in the ringbuffer.
Return value: Integer count of bytes written.
.. method:: RingIO.close()
No-op provided as part of standard `stream` interface. Has no effect
on data in the ringbuffer.

View File

@@ -43,7 +43,8 @@ Constructors
- *pin* is a machine.Pin instance. - *pin* is a machine.Pin instance.
- *n* is the number of LEDs in the strip. - *n* is the number of LEDs in the strip.
- *bpp* is 3 for RGB LEDs, and 4 for RGBW LEDs. - *bpp* is 3 for RGB LEDs, and 4 for RGBW LEDs.
- *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz). - *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz). You
may also supply a timing tuple as accepted by `machine.bitstream()`.
Pixel access methods Pixel access methods
-------------------- --------------------

View File

@@ -10,7 +10,7 @@ Example usage::
import network import network
nic = network.LAN(0) nic = network.LAN(0)
print(nic.ifconfig()) print(nic.ipconfig("addr4"))
# now use socket as usual # now use socket as usual
... ...

View File

@@ -0,0 +1,98 @@
.. currentmodule:: network
.. _network.PPP:
class PPP -- create network connections over serial PPP
=======================================================
This class allows you to create a network connection over a serial port using
the PPP protocol. It is only available on selected ports and boards.
Example usage::
import network
ppp = network.PPP(uart)
ppp.connect()
while not ppp.isconnected():
pass
print(ppp.ipconfig("addr4"))
# use the socket module as usual, etc
ppp.disconnect()
Constructors
------------
.. class:: PPP(stream)
Create a PPP driver object.
Arguments are:
- *stream* is any object that supports the stream protocol, but is most commonly a
:class:`machine.UART` instance. This stream object must have an ``irq()`` method
and an ``IRQ_RXIDLE`` constant, for use by `PPP.connect`.
Methods
-------
.. method:: PPP.connect(security=SEC_NONE, user=None, key=None)
Initiate a PPP connection with the given parameters:
- *security* is the type of security, either ``PPP.SEC_NONE``, ``PPP.SEC_PAP``,
or ``PPP.SEC_CHAP``.
- *user* is an optional user name to use with the security mode.
- *key* is an optional password to use with the security mode.
When this method is called the underlying stream has its interrupt configured to call
`PPP.poll` via ``stream.irq(ppp.poll, stream.IRQ_RXIDLE)``. This makes sure the
stream is polled, and data passed up the PPP stack, wheverver data becomes available
on the stream.
The connection proceeds asynchronously, in the background.
.. method:: PPP.disconnect()
Terminate the connection. This must be called to cleanly close the PPP connection.
.. method:: PPP.isconnected()
Returns ``True`` if the PPP link is connected and up.
Returns ``False`` otherwise.
.. method:: PPP.status()
Returns the PPP status.
.. method:: PPP.config(config_parameters)
Sets or gets parameters of the PPP interface. There are currently no parameter that
can be set or retrieved.
.. method:: PPP.ipconfig('param')
PPP.ipconfig(param=value, ...)
See `AbstractNIC.ipconfig`.
.. method:: PPP.ifconfig([(ip, subnet, gateway, dns)])
See `AbstractNIC.ifconfig`.
.. method:: PPP.poll()
Poll the underlying stream for data, and pass it up the PPP stack.
This is called automatically if the stream is a UART with a RXIDLE interrupt,
so it's not usually necessary to call it manually.
Constants
---------
.. data:: PPP.SEC_NONE
PPP.SEC_PAP
PPP.SEC_CHAP
The type of connection security.

View File

@@ -13,7 +13,7 @@ Example usage::
import network import network
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
print(nic.ifconfig()) print(nic.ipconfig("addr4"))
# now use socket as usual # now use socket as usual
... ...
@@ -51,20 +51,7 @@ Constructors
Methods Methods
------- -------
.. method:: WIZNET5K.isconnected() This class implements most methods from `AbstractNIC <AbstractNIC>`, which are documented there. Additional methods are:
Returns ``True`` if the physical Ethernet link is connected and up.
Returns ``False`` otherwise.
.. method:: WIZNET5K.ifconfig([(ip, subnet, gateway, dns)])
Get/set IP address, subnet mask, gateway and DNS.
When called with no arguments, this method returns a 4-tuple with the above information.
To set the above values, pass a 4-tuple with the required information. For example::
nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
.. method:: WIZNET5K.regs() .. method:: WIZNET5K.regs()

View File

@@ -107,7 +107,7 @@ Methods
Get or set general network interface parameters. These methods allow to work Get or set general network interface parameters. These methods allow to work
with additional parameters beyond standard IP configuration (as dealt with by with additional parameters beyond standard IP configuration (as dealt with by
`WLAN.ifconfig()`). These include network-specific and hardware-specific `AbstractNIC.ipconfig()`). These include network-specific and hardware-specific
parameters. For setting parameters, keyword argument syntax should be used, parameters. For setting parameters, keyword argument syntax should be used,
multiple parameters can be set at once. For querying, parameters name should multiple parameters can be set at once. For querying, parameters name should
be quoted as a string, and only one parameter can be queries at time:: be quoted as a string, and only one parameter can be queries at time::

View File

@@ -20,7 +20,7 @@ This class provides a driver for the WiFi network processor in the WiPy. Example
wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key')) wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key'))
while not wlan.isconnected(): while not wlan.isconnected():
time.sleep_ms(50) time.sleep_ms(50)
print(wlan.ifconfig()) print(wlan.ipconfig("addr4"))
# now use socket as usual # now use socket as usual
... ...
@@ -96,16 +96,10 @@ Methods
In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address. In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address.
In AP mode returns ``True`` when a station is connected, ``False`` otherwise. In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
.. method:: WLANWiPy.ifconfig(if_id=0, config=['dhcp' or configtuple]) .. method:: WLANWiPy.ipconfig('param')
WLANWiPy.ipconfig(param=value, ...)
With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*. See :meth:`AbstractNIC.ipconfig <AbstractNIC.ipconfig>`. Supported parameters are: ``dhcp4``, ``addr4``, ``gw4``.
if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
are negotiated with the AP.
If the 4-tuple config is given then a static IP is configured. For instance::
wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
.. method:: WLANWiPy.mode([mode]) .. method:: WLANWiPy.mode([mode])

View File

@@ -24,7 +24,7 @@ For example::
print("Waiting for connection...") print("Waiting for connection...")
while not nic.isconnected(): while not nic.isconnected():
time.sleep(1) time.sleep(1)
print(nic.ifconfig()) print(nic.ipconfig("addr4"))
# now use socket as usual # now use socket as usual
import socket import socket
@@ -113,8 +113,48 @@ parameter should be `id`.
connected to the AP. The list contains tuples of the form connected to the AP. The list contains tuples of the form
(MAC, RSSI). (MAC, RSSI).
.. method:: AbstractNIC.ipconfig('param')
AbstractNIC.ipconfig(param=value, ...)
Get or set interface-specific IP-configuration interface parameters.
Supported parameters are the following (availability of a particular
parameter depends on the port and the specific network interface):
* ``dhcp4`` (``True/False``) obtain an IPv4 address, gateway and dns
server via DHCP. This method does not block and wait for an address
to be obtained. To check if an address was obtained, use the read-only
property ``has_dhcp4``.
* ``gw4`` Get/set the IPv4 default-gateway.
* ``dhcp6`` (``True/False``) obtain a DNS server via stateless DHCPv6.
Obtaining IP Addresses via DHCPv6 is currently not implemented.
* ``autoconf6`` (``True/False``) obtain a stateless IPv6 address via
the network prefix shared in router advertisements. To check if a
stateless address was obtained, use the read-only
property ``has_autoconf6``.
* ``addr4`` (e.g. ``192.168.0.4/24``) obtain the current IPv4 address
and network mask as ``(ip, subnet)``-tuple, regardless of how this
address was obtained. This method can be used to set a static IPv4
address either as ``(ip, subnet)``-tuple or in CIDR-notation.
* ``addr6`` (e.g. ``fe80::1234:5678``) obtain a list of current IPv6
addresses as ``(ip, state, preferred_lifetime, valid_lifetime)``-tuple.
This include link-local, slaac and static addresses.
``preferred_lifetime`` and ``valid_lifetime`` represent the remaining
valid and preferred lifetime of each IPv6 address, in seconds.
``state`` indicates the current state of the address:
* ``0x08`` - ``0x0f`` indicates the address is tentative, counting the
number of probes sent.
* ``0x10`` The address is deprecated (but still valid)
* ``0x30`` The address is preferred (and valid)
* ``0x40`` The address is duplicated and can not be used.
This method can be used to set a static IPv6
address, by setting this parameter to the address, like ``fe80::1234:5678``.
.. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)]) .. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)])
.. note:: This function is deprecated, use `ipconfig()` instead.
Get/set IP-level network interface parameters: IP address, subnet mask, Get/set IP-level network interface parameters: IP address, subnet mask,
gateway and DNS server. When called with no arguments, this method returns gateway and DNS server. When called with no arguments, this method returns
a 4-tuple with the above information. To set the above values, pass a a 4-tuple with the above information. To set the above values, pass a
@@ -127,7 +167,7 @@ parameter should be `id`.
Get or set general network interface parameters. These methods allow to work Get or set general network interface parameters. These methods allow to work
with additional parameters beyond standard IP configuration (as dealt with by with additional parameters beyond standard IP configuration (as dealt with by
`ifconfig()`). These include network-specific and hardware-specific `ipconfig()`). These include network-specific and hardware-specific
parameters. For setting parameters, the keyword argument parameters. For setting parameters, the keyword argument
syntax should be used, and multiple parameters can be set at once. For syntax should be used, and multiple parameters can be set at once. For
querying, a parameter name should be quoted as a string, and only one querying, a parameter name should be quoted as a string, and only one
@@ -152,6 +192,7 @@ provide a way to control networking interfaces of various kinds.
network.WLANWiPy.rst network.WLANWiPy.rst
network.WIZNET5K.rst network.WIZNET5K.rst
network.LAN.rst network.LAN.rst
network.PPP.rst
Network functions Network functions
================= =================
@@ -195,6 +236,20 @@ The following are functions available in the network module.
The default hostname is typically the name of the board. The default hostname is typically the name of the board.
.. function:: ipconfig('param')
ipconfig(param=value, ...)
Get or set global IP-configuration parameters.
Supported parameters are the following (availability of a particular
parameter depends on the port and the specific network interface):
* ``dns`` Get/set DNS server. This method can support both, IPv4 and
IPv6 addresses.
* ``prefer`` (``4/6``) Specify which address type to return, if a domain
name has both A and AAAA records. Note, that this does not clear the
local DNS cache, so that any previously obtained addresses might not
change.
.. function:: phy_mode([mode]) .. function:: phy_mode([mode])
Get or set the PHY mode. Get or set the PHY mode.

View File

@@ -27,6 +27,17 @@ Constructors
Methods Methods
------- -------
.. method:: PIO.gpio_base([base])
Query and optionally set the current GPIO base for this PIO instance.
If an argument is given then it must be a pin (or integer corresponding to a pin
number), restricted to either GPIO0 or GPIO16. The GPIO base will then be set to
that pin. Setting the GPIO base must be done before any programs are added or state
machines created.
Returns the current GPIO base pin.
.. method:: PIO.add_program(program) .. method:: PIO.add_program(program)
Add the *program* to the instruction memory of this PIO instance. Add the *program* to the instruction memory of this PIO instance.

View File

@@ -438,6 +438,10 @@ The i.MXRT MCU supports battery backup of the RTC. By connecting a battery of
current drawn from the battery is ~20µA, which is rather high. A CR2032 coin current drawn from the battery is ~20µA, which is rather high. A CR2032 coin
cell will last for about one year. cell will last for about one year.
Note: In v1.23.0 the support for subseconds was removed. When reading the RTC, 0 will
be returned as value for subsecond, When setting the RTC time, the subsecond
field is ignored. The RTC itself does not provide a microsecond value.
SD card SD card
------- -------
@@ -528,7 +532,7 @@ Ethernet. Example usage::
lan.active(True) lan.active(True)
If there is a DHCP server in the LAN, the IP address is supplied by that server. If there is a DHCP server in the LAN, the IP address is supplied by that server.
Otherwise, the IP address can be set with lan.ifconfig(). The default address Otherwise, the IP address can be set with lan.ipconfig(addr4="..."). The default address
is 192.168.0.1. is 192.168.0.1.
Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an

View File

@@ -227,11 +227,12 @@ The full list of supported commands are:
- ``cat <file..>`` to show the contents of a file or files on the device - ``cat <file..>`` to show the contents of a file or files on the device
- ``ls`` to list the current directory - ``ls`` to list the current directory
- ``ls <dirs...>`` to list the given directories - ``ls <dirs...>`` to list the given directories
- ``cp [-r] <src...> <dest>`` to copy files - ``cp [-rf] <src...> <dest>`` to copy files
- ``rm <src...>`` to remove files on the device - ``rm <src...>`` to remove files on the device
- ``mkdir <dirs...>`` to create directories on the device - ``mkdir <dirs...>`` to create directories on the device
- ``rmdir <dirs...>`` to remove directories on the device - ``rmdir <dirs...>`` to remove directories on the device
- ``touch <file..>`` to create the files (if they don't already exist) - ``touch <file..>`` to create the files (if they don't already exist)
- ``sha256sum <file..>`` to calculate the SHA256 sum of files
The ``cp`` command uses a convention where a leading ``:`` represents a remote 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 path. Without a leading ``:`` means a local path. This is based on the
@@ -256,6 +257,11 @@ The full list of supported commands are:
This will copy the file to the device then enter the REPL. The ``+`` prevents This will copy the file to the device then enter the REPL. The ``+`` prevents
``"repl"`` being interpreted as a path. ``"repl"`` being interpreted as a path.
The ``cp`` command supports the ``-r`` option to make a recursive copy. By
default ``cp`` will skip copying files to the remote device if the SHA256 hash
of the source and destination file matches. To force a copy regardless of the
hash use the ``-f`` option.
**Note:** For convenience, all of the filesystem sub-commands are also **Note:** For convenience, all of the filesystem sub-commands are also
:ref:`aliased as regular commands <mpremote_shortcuts>`, i.e. you can write :ref:`aliased as regular commands <mpremote_shortcuts>`, i.e. you can write
``mpremote cp ...`` instead of ``mpremote fs cp ...``. ``mpremote cp ...`` instead of ``mpremote fs cp ...``.
@@ -469,9 +475,9 @@ An example ``config.py`` might look like:
for ap in wl.scan(): for ap in wl.scan():
print(ap) print(ap)
""",], # Print out nearby WiFi networks. """,], # Print out nearby WiFi networks.
"wl_ifconfig": [ "wl_ipconfig": [
"exec", "exec",
"import network; sta_if = network.WLAN(network.STA_IF); print(sta_if.ifconfig())", "import network; sta_if = network.WLAN(network.STA_IF); print(sta_if.ipconfig('addr4'))",
""",], # Print ip address of station interface. """,], # Print ip address of station interface.
"test": ["mount", ".", "exec", "import test"], # Mount current directory and run test.py. "test": ["mount", ".", "exec", "import test"], # Mount current directory and run test.py.
"demo": ["run", "path/to/demo.py"], # Execute demo.py on the device. "demo": ["run", "path/to/demo.py"], # Execute demo.py on the device.

View File

@@ -58,7 +58,7 @@ If importing an .mpy file fails then try the following:
sys_mpy = sys.implementation._mpy sys_mpy = sys.implementation._mpy
arch = [None, 'x86', 'x64', arch = [None, 'x86', 'x64',
'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp', 'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp',
'xtensa', 'xtensawin'][sys_mpy >> 10] 'xtensa', 'xtensawin', 'rv32imc'][sys_mpy >> 10]
print('mpy version:', sys_mpy & 0xff) print('mpy version:', sys_mpy & 0xff)
print('mpy sub-version:', sys_mpy >> 8 & 3) print('mpy sub-version:', sys_mpy >> 8 & 3)
print('mpy flags:', end='') print('mpy flags:', end='')

View File

@@ -120,9 +120,8 @@ Some more examples::
# Same, but using . instead. # Same, but using . instead.
$ pyboard.py --device /dev/ttyACM0 -f cp :main.py . $ pyboard.py --device /dev/ttyACM0 -f cp :main.py .
# Copy three files to the device, keeping their names # Copy three files to the device, keeping their names.
# and paths (note: `lib` must exist on the device) $ pyboard.py --device /dev/ttyACM0 -f cp main.py app.py foo.py :
$ pyboard.py --device /dev/ttyACM0 -f cp main.py app.py lib/foo.py :
# Remove a file from the device. # Remove a file from the device.
$ pyboard.py --device /dev/ttyACM0 -f rm util.py $ pyboard.py --device /dev/ttyACM0 -f rm util.py

View File

@@ -31,12 +31,25 @@ The MicroPython REPL is accessed via the USB serial port. Tab-completion is usef
find out what methods an object has. Paste mode (ctrl-E) is useful to paste a find out what methods an object has. Paste mode (ctrl-E) is useful to paste a
large slab of Python code into the REPL. large slab of Python code into the REPL.
The :mod:`machine` module:: The :mod:`machine` module:
machine.freq() allows to change the MCU frequency and control the peripheral
frequency for UART and SPI. Usage::
machine.freq(MCU_frequency[, peripheral_frequency=48_000_000])
The MCU frequency can be set in a range from less than 48 MHz to about 250MHz.
The default at boot time is 125 MHz. The peripheral frequency must be either
48 MHz or identical to the MCU frequency, with 48 MHz as the default.
If the peripheral frequency is changed, any already existing instance of
UART and SPI will change it's baud rate and may have to be re-configured::
import machine import machine
machine.freq() # get the current frequency of the CPU machine.freq() # get the current frequency of the CPU
machine.freq(240000000) # set the CPU frequency to 240 MHz machine.freq(240000000) # set the CPU frequency to 240 MHz and keep
# the UART frequency at 48MHz
machine.freq(125000000, 125000000) # set the CPU and UART frequency to 125 MHz
The :mod:`rp2` module:: The :mod:`rp2` module::
@@ -187,6 +200,14 @@ Use the :ref:`machine.ADC <machine.ADC>` class::
adc = ADC(Pin(26)) # create ADC object on ADC pin adc = ADC(Pin(26)) # create ADC object on ADC pin
adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v
The argument of the constructor ADC specifies either a Pin by number, name of as
Pin object, or a channel number in the range 0 - 3 or ADC.CORE_TEMP for the
internal temperature sensor. If a pin is specified,
the pin is initialized in high-Z mode. If a channel number is used, the pin
is not initialized and configuring is left to the user code. After hard reset,
RP2040 pins operate in current sink mode at about 60µA. If the pin is not
otherwise configured, that may lead to wrong ADC readings.
Software SPI bus Software SPI bus
---------------- ----------------

View File

@@ -65,6 +65,8 @@ Use the :mod:`time <time>` module::
start = time.ticks_ms() # get millisecond counter start = time.ticks_ms() # get millisecond counter
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
Note that :func:`time.sleep_us()` delays by busy waiting. During that time, other tasks are
not scheduled.
Clock and time Clock and time
-------------- --------------

View File

@@ -184,18 +184,18 @@ WLAN (WiFi)
See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. :: See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. ::
import machine import machine, network
from network import WLAN from network import WLAN
# configure the WLAN subsystem in station mode (the default is AP) # configure the WLAN subsystem in station mode (the default is AP)
wlan = WLAN(mode=WLAN.STA) wlan = WLAN(mode=WLAN.STA)
# go for fixed IP settings # go for fixed IP settings
wlan.ifconfig(config=('192.168.0.107', '255.255.255.0', '192.168.0.1', '8.8.8.8')) network.ipconfig(dns='8.8.8.8')
wlan.ipconfig(addr4='192.168.0.107/24', gw4='192.168.0.1')
wlan.scan() # scan for available networks wlan.scan() # scan for available networks
wlan.connect(ssid='mynetwork', auth=(WLAN.WPA2, 'mynetworkkey')) wlan.connect(ssid='mynetwork', auth=(WLAN.WPA2, 'mynetworkkey'))
while not wlan.isconnected(): while not wlan.isconnected():
pass pass
print(wlan.ifconfig())
# enable wake on WLAN # enable wake on WLAN
wlan.irq(trigger=WLAN.ANY_EVENT, wake=machine.SLEEP) wlan.irq(trigger=WLAN.ANY_EVENT, wake=machine.SLEEP)
# go to sleep # go to sleep

View File

@@ -50,14 +50,15 @@ Assigning a static IP address when booting
If you want your WiPy to connect to your home router after boot-up, and with a fixed If you want your WiPy to connect to your home router after boot-up, and with a fixed
IP address so that you can access it via telnet or FTP, use the following script as /flash/boot.py:: IP address so that you can access it via telnet or FTP, use the following script as /flash/boot.py::
import machine import machine, network
from network import WLAN from network import WLAN
wlan = WLAN() # get current object, without changing the mode wlan = WLAN() # get current object, without changing the mode
if machine.reset_cause() != machine.SOFT_RESET: if machine.reset_cause() != machine.SOFT_RESET:
wlan.init(WLAN.STA) wlan.init(WLAN.STA)
# configuration below MUST match your home router settings!! # configuration below MUST match your home router settings!!
wlan.ifconfig(config=('192.168.178.107', '255.255.255.0', '192.168.178.1', '8.8.8.8')) network.ipconfig(dns='8.8.8.8')
wlan.ipconfig(addr4='192.168.0.107/24', gw4='192.168.0.1')
if not wlan.isconnected(): if not wlan.isconnected():
# change the line below to match your network ssid, security and password # change the line below to match your network ssid, security and password

View File

@@ -36,7 +36,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
from machine import Pin from machine import Pin
pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1 pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B
print(pin) # print pin port and number print(pin) # print pin port and number
pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin
@@ -47,14 +47,14 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
pin.on() # set pin to high pin.on() # set pin to high
pin.off() # set pin to low pin.off() # set pin to low
pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1 pin = Pin(("gpiob", 21), Pin.IN) # create input pin on GPIO port B
pin = Pin(("GPIO_1", 21), Pin.OUT, value=1) # set pin high on creation pin = Pin(("gpiob", 21), Pin.OUT, value=1) # set pin high on creation
pin = Pin(("GPIO_1", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor pin = Pin(("gpiob", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
switch = Pin(("GPIO_2", 6), Pin.IN) # create input pin for a switch 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 switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed
Hardware I2C bus Hardware I2C bus
---------------- ----------------
@@ -63,7 +63,7 @@ Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class::
from machine import I2C from machine import I2C
i2c = I2C("I2C_0") # construct an i2c bus i2c = I2C("i2c0") # construct an i2c bus
print(i2c) # print device name print(i2c) # print device name
i2c.scan() # scan the device for available I2C slaves i2c.scan() # scan the device for available I2C slaves
@@ -84,11 +84,11 @@ Hardware SPI is accessed via the :ref:`machine.SPI <machine.SPI>` class::
from machine import SPI from machine import SPI
spi = SPI("SPI_0") # construct a spi bus with default configuration spi = SPI("spi0") # construct a spi bus with default configuration
spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration
# equivalently, construct spi bus and set configuration at the same time # equivalently, construct spi bus and set configuration at the same time
spi = SPI("SPI_0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) spi = SPI("spi0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
print(spi) # print device name and bus configuration print(spi) # print device name and bus configuration
spi.read(4) # read 4 bytes on MISO spi.read(4) # read 4 bytes on MISO
@@ -146,7 +146,7 @@ Use the :ref:`zsensor.Sensor <zsensor.Sensor>` class to access sensor data::
import zsensor import zsensor
from zsensor import Sensor from zsensor import Sensor
accel = Sensor("FXOX8700") # create sensor object for the accelerometer accel = Sensor("fxos8700") # create sensor object for the accelerometer
accel.measure() # obtain a measurement reading from the accelerometer accel.measure() # obtain a measurement reading from the accelerometer

View File

@@ -31,8 +31,8 @@ With your serial program open (PuTTY, screen, picocom, etc) you may see a
blank screen with a flashing cursor. Press Enter (or reset the board) and blank screen with a flashing cursor. Press Enter (or reset the board) and
you should be presented with the following text:: you should be presented with the following text::
*** Booting Zephyr OS build zephyr-v3.1.0 *** *** Booting Zephyr OS build v3.7.0 ***
MicroPython v1.19.1-9-g4fd54a475 on 2022-06-17; zephyr-frdm_k64f with mk64f12 MicroPython v1.24.0-preview.179.g5b85b24bd on 2024-08-05; zephyr-frdm_k64f with mk64f12
Type "help()" for more information. Type "help()" for more information.
>>> >>>

View File

@@ -44,28 +44,36 @@ int mp_soft_spi_ioctl(void *self_in, uint32_t cmd) {
return 0; return 0;
} }
static uint8_t swap_bits(uint8_t byte) {
const static uint8_t swap_table[16] = {
0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
};
return ((swap_table[byte & 0x0f] << 4) | swap_table[byte >> 4]);
}
void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) { void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t*)self_in; mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t*)self_in;
uint32_t delay_half = self->delay_half; uint32_t delay_half = self->delay_half;
// only MSB transfer is implemented
// If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured // If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured
// delay_half is equal to this value, then the software SPI implementation // delay_half is equal to this value, then the software SPI implementation
// will run as fast as possible, limited only by CPU speed and GPIO time. // will run as fast as possible, limited only by CPU speed and GPIO time.
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY #ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) { if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) {
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i]; uint8_t data_out = self->firstbit != MICROPY_PY_MACHINE_SPI_MSB ?
src[i] : swap_bits(src[i]);
uint8_t data_in = 0; uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) { for (int j = 0; j < 8; ++j, data_out >>= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1); mp_hal_pin_write(self->mosi, data_out & 1);
mp_hal_pin_write(self->sck, 1 - self->polarity); mp_hal_pin_write(self->sck, 1 - self->polarity);
data_in = (data_in << 1) | mp_hal_pin_read(self->miso); data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
mp_hal_pin_write(self->sck, self->polarity); mp_hal_pin_write(self->sck, self->polarity);
} }
if (dest != NULL) { if (dest != NULL) {
dest[i] = data_in; dest[i] = self->firstbit == MICROPY_PY_MACHINE_SPI_MSB ?
data_in : swap_bits(data_in);
} }
} }
return; return;
@@ -73,10 +81,11 @@ void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t
#endif #endif
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i]; uint8_t data_out = self->firstbit != MICROPY_PY_MACHINE_SPI_MSB ?
src[i] : swap_bits(src[i]);
uint8_t data_in = 0; uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) { for (int j = 0; j < 8; ++j, data_out >>= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1); mp_hal_pin_write(self->mosi, data_out & 1);
if (self->phase == 0) { if (self->phase == 0) {
mp_hal_delay_us_fast(delay_half); mp_hal_delay_us_fast(delay_half);
mp_hal_pin_write(self->sck, 1 - self->polarity); mp_hal_pin_write(self->sck, 1 - self->polarity);
@@ -94,7 +103,8 @@ void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t
} }
} }
if (dest != NULL) { if (dest != NULL) {
dest[i] = data_in; dest[i] = self->firstbit == MICROPY_PY_MACHINE_SPI_MSB ?
data_in : swap_bits(data_in);
} }
} }
} }

View File

@@ -42,6 +42,7 @@ typedef struct _mp_soft_spi_obj_t {
uint32_t delay_half; // microsecond delay for half SCK period uint32_t delay_half; // microsecond delay for half SCK period
uint8_t polarity; uint8_t polarity;
uint8_t phase; uint8_t phase;
uint8_t firstbit;
mp_hal_pin_obj_t sck; mp_hal_pin_obj_t sck;
mp_hal_pin_obj_t mosi; mp_hal_pin_obj_t mosi;
mp_hal_pin_obj_t miso; mp_hal_pin_obj_t miso;

View File

@@ -95,7 +95,7 @@ typedef enum {
// AP mode commands. // AP mode commands.
NINA_CMD_START_AP_OPEN = 0x18, NINA_CMD_START_AP_OPEN = 0x18,
NINA_CMD_START_AP_WEP = 0x19, NINA_CMD_START_AP_WPA = 0x19,
// AP mode scan commands. // AP mode scan commands.
NINA_CMD_AP_START_SCAN = 0x36, NINA_CMD_AP_START_SCAN = 0x36,
@@ -395,7 +395,7 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
uint8_t status = NINA_STATUS_AP_FAILED; uint8_t status = NINA_STATUS_AP_FAILED;
if ((key == NULL && security != NINA_SEC_OPEN) || if ((key == NULL && security != NINA_SEC_OPEN) ||
(security != NINA_SEC_OPEN && security != NINA_SEC_WEP)) { (security != NINA_SEC_OPEN && security != NINA_SEC_WPA_PSK)) {
return -1; return -1;
} }
@@ -406,8 +406,8 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
return -1; return -1;
} }
break; break;
case NINA_SEC_WEP: case NINA_SEC_WPA_PSK:
if (nina_send_command_read_ack(NINA_CMD_START_AP_WEP, if (nina_send_command_read_ack(NINA_CMD_START_AP_WPA,
3, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_STR(key), ARG_BYTE(channel))) != SPI_ACK) { 3, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_STR(key), ARG_BYTE(channel))) != SPI_ACK) {
return -1; return -1;
} }

View File

@@ -1,12 +1,12 @@
# Dynamic Native Modules # Dynamic Native Modules
Dynamic Native Modules are .mpy files that contain native machine code from a Dynamic Native Modules are .mpy files that contain native machine code from a
language other than Python. For more info see [the documentation] language other than Python. For more info see [the
(https://docs.micropython.org/en/latest/develop/natmod.html). documentation](https://docs.micropython.org/en/latest/develop/natmod.html).
This should not be confused with [User C Modules] This should not be confused with [User C
(https://docs.micropython.org/en/latest/develop/cmodules.html) which are a Modules](https://docs.micropython.org/en/latest/develop/cmodules.html) which are
mechanism to add additional out-of-tree modules into the firmware build. a mechanism to add additional out-of-tree modules into the firmware build.
## Examples ## Examples

View File

@@ -11,7 +11,7 @@
const char *stack_top; const char *stack_top;
void mp_stack_check(void) { void mp_cstack_check(void) {
// Assumes descending stack on target // Assumes descending stack on target
volatile char dummy; volatile char dummy;
if (stack_top - &dummy >= STACK_LIMIT) { if (stack_top - &dummy >= STACK_LIMIT) {

View File

@@ -1,27 +1,52 @@
# Very simple HTTP client example:
# - Connects to a server.
# - Sends a HTTP request.
# - Reads the result.
#
# This example works in both MicroPython and CPython.
#
# To implement an HTTP client using less code, use mip to install the requests package:
# https://github.com/micropython/micropython-lib/tree/master/python-ecosys/requests
import socket import socket
def main(use_stream=False): # `addr_family` selects IPv4 vs IPv6: 0 means either, or use
s = socket.socket() # socket.AF_INET or socket.AF_INET6 to select a particular one.
def main(url, addr_family=0, use_stream=False):
# Split the given URL into components.
proto, _, host, path = url.split(b"/", 3)
assert proto == b"http:"
ai = socket.getaddrinfo("google.com", 80) # Lookup the server address, for the given family and socket type.
ai = socket.getaddrinfo(host, 80, addr_family, socket.SOCK_STREAM)
print("Address infos:", ai) print("Address infos:", ai)
addr = ai[0][-1]
# Select the first address.
ai = ai[0]
# Create a socket with the server's family, type and proto.
s = socket.socket(ai[0], ai[1], ai[2])
# Connect to the server.
addr = ai[-1]
print("Connect address:", addr) print("Connect address:", addr)
s.connect(addr) s.connect(addr)
# Send request and read response.
request = b"GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host)
if use_stream: if use_stream:
# MicroPython socket objects support stream (aka file) interface # MicroPython socket objects support stream (aka file) interface
# directly, but the line below is needed for CPython. # directly, but the line below is needed for CPython.
s = s.makefile("rwb", 0) s = s.makefile("rwb", 0)
s.write(b"GET / HTTP/1.0\r\n\r\n") s.write(request)
print(s.read()) print(s.read())
else: else:
s.send(b"GET / HTTP/1.0\r\n\r\n") s.send(request)
print(s.recv(4096)) print(s.recv(4096))
# Close the socket.
s.close() s.close()
main() main(b"http://www.google.com/")

View File

@@ -1,32 +1,62 @@
# Very simple HTTPS client example:
# - Connects to a server.
# - Upgrades the connection to a TLS connection.
# - Sends a HTTP request.
# - Reads the result.
#
# This example works in both MicroPython and CPython.
#
# To implement an HTTPS client using less code, use mip to install the requests package:
# https://github.com/micropython/micropython-lib/tree/master/python-ecosys/requests
import socket import socket
import ssl import ssl
def main(use_stream=True): # `addr_family` selects IPv4 vs IPv6: 0 means either, or use
s = socket.socket() # socket.AF_INET or socket.AF_INET6 to select a particular one.
def main(url, addr_family=0, use_stream=True):
# Split the given URL into components.
proto, _, host, path = url.split(b"/", 3)
assert proto == b"https:"
ai = socket.getaddrinfo("google.com", 443) # Lookup the server address, for the given family and socket type.
ai = socket.getaddrinfo(host, 443, addr_family, socket.SOCK_STREAM)
print("Address infos:", ai) print("Address infos:", ai)
addr = ai[0][-1]
# Select the first address.
ai = ai[0]
# Create a socket with the server's family, type and proto.
s = socket.socket(ai[0], ai[1], ai[2])
# Connect to the server.
addr = ai[-1]
print("Connect address:", addr) print("Connect address:", addr)
s.connect(addr) s.connect(addr)
s = ssl.wrap_socket(s) # Upgrade the socket to a TLS connection.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
s = ctx.wrap_socket(s)
print(s) print(s)
# Send request and read response.
request = b"GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host)
if use_stream: if use_stream:
# Both CPython and MicroPython SSLSocket objects support read() and # Both CPython and MicroPython SSLSocket objects support read() and
# write() methods. # write() methods.
s.write(b"GET / HTTP/1.0\r\n\r\n") s.write(request)
print(s.read(4096)) print(s.read(4096))
else: else:
# MicroPython SSLSocket objects implement only stream interface, not # MicroPython SSLSocket objects implement only stream interface, not
# socket interface # socket interface
s.send(b"GET / HTTP/1.0\r\n\r\n") s.send(request)
print(s.recv(4096)) print(s.recv(4096))
# Close the socket.
s.close() s.close()
main() main(b"https://www.google.com/")

View File

@@ -37,13 +37,13 @@ def read_nonblocking(poller, sock, n):
return data return data
def main(url): def main(url, addr_family=0):
# Split the given URL into components. # Split the given URL into components.
proto, _, host, path = url.split(b"/", 3) proto, _, host, path = url.split(b"/", 3)
assert proto == b"https:" assert proto == b"https:"
# Note: this getaddrinfo() call is blocking! # Note: this getaddrinfo() call is blocking!
ai = socket.getaddrinfo(host, 443)[0] ai = socket.getaddrinfo(host, 443, addr_family, socket.SOCK_STREAM)[0]
addr = ai[-1] addr = ai[-1]
print("Connect address:", addr) print("Connect address:", addr)

View File

@@ -68,6 +68,87 @@ MP_DEFINE_CONST_OBJ_TYPE(
locals_dict, &example_Timer_locals_dict locals_dict, &example_Timer_locals_dict
); );
// What follows is a *separate* class definition that demonstrates more
// advanced techniques to implement other Python-like features, such as:
//
// - A custom representation for __repr__ and __str__.
// - Custom attribute handling to create a read/write "property".
//
// It re-uses some of the elements of the basic Timer class. This is allowed
// because they both use example_Timer_obj_t as the instance structure.
// Handles AdvancedTimer.__repr__, AdvancedTimer.__str__.
static void example_AdvancedTimer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
// Get the elapsed time. In this case, it's also a demonstration of calling
// the equivalent of self.time() in the C API. This is not usually very
// efficient, but it can sometimes be useful.
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);
// 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);
}
}
// Handles AdvancedTimer.seconds for reading and writing.
static void example_AdvancedTimer_attribute_handler(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
// In this example, we only want to handle the .seconds attribute in a
// special way.
if (attr != MP_QSTR_seconds) {
// Attribute not found, continue lookup in locals dict. This way,
// methods like .time() will be handled normally.
dest[1] = MP_OBJ_SENTINEL;
return;
}
// Get reference to AdvancedTimer instance.
example_Timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Check if this is a read operation.
if (dest[0] == MP_OBJ_NULL) {
// It's read, so "return" elapsed seconds by storing it in dest[0].
mp_uint_t elapsed = mp_hal_ticks_ms() - self->start_time;
dest[0] = mp_obj_new_int_from_uint(elapsed / 1000);
return;
}
// Check if this is a delete or store operation.
else if (dest[0] == MP_OBJ_SENTINEL) {
// It's delete or store. Now check which one.
if (dest[1] == MP_OBJ_NULL) {
// It's delete. But in this example we don't want to allow it
// so we just return.
return;
} else {
// It's write. First, get the value that the user is trying to set.
mp_uint_t desired_ms = mp_obj_get_int(dest[1]) * 1000;
// Use it to update the start time. This way, the next read will
// report the updated time.
self->start_time = mp_hal_ticks_ms() - desired_ms;
// Indicate successful store.
dest[0] = MP_OBJ_NULL;
return;
}
}
}
// This defines the type(AdvancedTimer) object.
MP_DEFINE_CONST_OBJ_TYPE(
example_type_AdvancedTimer,
MP_QSTR_AdvancedTimer,
MP_TYPE_FLAG_NONE,
attr, example_AdvancedTimer_attribute_handler,
print, example_AdvancedTimer_print,
make_new, example_Timer_make_new,
locals_dict, &example_Timer_locals_dict
);
// Define all attributes of the module. // Define all attributes of the module.
// Table entries are key/value pairs of the attribute name (a string) // Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference. // and the MicroPython object reference.
@@ -77,6 +158,7 @@ static const mp_rom_map_elem_t example_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) },
{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) }, { MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) },
{ MP_ROM_QSTR(MP_QSTR_AdvancedTimer), MP_ROM_PTR(&example_type_AdvancedTimer) },
}; };
static MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); static MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);

View File

@@ -49,6 +49,7 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/network_cyw43.c ${MICROPY_EXTMOD_DIR}/network_cyw43.c
${MICROPY_EXTMOD_DIR}/network_lwip.c ${MICROPY_EXTMOD_DIR}/network_lwip.c
${MICROPY_EXTMOD_DIR}/network_ninaw10.c ${MICROPY_EXTMOD_DIR}/network_ninaw10.c
${MICROPY_EXTMOD_DIR}/network_ppp_lwip.c
${MICROPY_EXTMOD_DIR}/network_wiznet5k.c ${MICROPY_EXTMOD_DIR}/network_wiznet5k.c
${MICROPY_EXTMOD_DIR}/os_dupterm.c ${MICROPY_EXTMOD_DIR}/os_dupterm.c
${MICROPY_EXTMOD_DIR}/vfs.c ${MICROPY_EXTMOD_DIR}/vfs.c
@@ -275,11 +276,14 @@ if(MICROPY_PY_LWIP)
target_sources(micropy_lib_lwip INTERFACE target_sources(micropy_lib_lwip INTERFACE
${MICROPY_DIR}/shared/netutils/netutils.c ${MICROPY_DIR}/shared/netutils/netutils.c
${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns.c ${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns.c
${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns_domain.c
${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns_out.c
${MICROPY_LIB_LWIP_DIR}/core/def.c ${MICROPY_LIB_LWIP_DIR}/core/def.c
${MICROPY_LIB_LWIP_DIR}/core/dns.c ${MICROPY_LIB_LWIP_DIR}/core/dns.c
${MICROPY_LIB_LWIP_DIR}/core/inet_chksum.c ${MICROPY_LIB_LWIP_DIR}/core/inet_chksum.c
${MICROPY_LIB_LWIP_DIR}/core/init.c ${MICROPY_LIB_LWIP_DIR}/core/init.c
${MICROPY_LIB_LWIP_DIR}/core/ip.c ${MICROPY_LIB_LWIP_DIR}/core/ip.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/acd.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/autoip.c ${MICROPY_LIB_LWIP_DIR}/core/ipv4/autoip.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/dhcp.c ${MICROPY_LIB_LWIP_DIR}/core/ipv4/dhcp.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/etharp.c ${MICROPY_LIB_LWIP_DIR}/core/ipv4/etharp.c
@@ -310,6 +314,32 @@ if(MICROPY_PY_LWIP)
${MICROPY_LIB_LWIP_DIR}/core/timeouts.c ${MICROPY_LIB_LWIP_DIR}/core/timeouts.c
${MICROPY_LIB_LWIP_DIR}/core/udp.c ${MICROPY_LIB_LWIP_DIR}/core/udp.c
${MICROPY_LIB_LWIP_DIR}/netif/ethernet.c ${MICROPY_LIB_LWIP_DIR}/netif/ethernet.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/auth.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ccp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/chap-md5.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/chap_ms.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/chap-new.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/demand.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/eap.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ecp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/eui64.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/fsm.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ipcp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ipv6cp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/lcp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/magic.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/mppe.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/multilink.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/polarssl/md5.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppapi.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/ppp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppcrypt.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppoe.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppol2tp.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/pppos.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/upap.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/utils.c
${MICROPY_LIB_LWIP_DIR}/netif/ppp/vj.c
) )
list(APPEND MICROPY_INC_CORE list(APPEND MICROPY_INC_CORE

View File

@@ -42,6 +42,7 @@ SRC_EXTMOD_C += \
extmod/modsocket.c \ extmod/modsocket.c \
extmod/modtls_axtls.c \ extmod/modtls_axtls.c \
extmod/modtls_mbedtls.c \ extmod/modtls_mbedtls.c \
extmod/mbedtls/mbedtls_alt.c \
extmod/modtime.c \ extmod/modtime.c \
extmod/moductypes.c \ extmod/moductypes.c \
extmod/modvfs.c \ extmod/modvfs.c \
@@ -51,6 +52,7 @@ SRC_EXTMOD_C += \
extmod/network_esp_hosted.c \ extmod/network_esp_hosted.c \
extmod/network_lwip.c \ extmod/network_lwip.c \
extmod/network_ninaw10.c \ extmod/network_ninaw10.c \
extmod/network_ppp_lwip.c \
extmod/network_wiznet5k.c \ extmod/network_wiznet5k.c \
extmod/os_dupterm.c \ extmod/os_dupterm.c \
extmod/vfs.c \ extmod/vfs.c \
@@ -167,6 +169,7 @@ SRC_LIB_LIBM_DBL_SQRT_HW_C += lib/libm_dbl/thumb_vfp_sqrt.c
# Too many warnings in libm_dbl, disable for now. # Too many warnings in libm_dbl, disable for now.
$(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-double-promotion -Wno-float-conversion $(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-double-promotion -Wno-float-conversion
$(BUILD)/lib/libm_dbl/__rem_pio2_large.o: CFLAGS += -Wno-maybe-uninitialized
################################################################################ ################################################################################
# VFS FAT FS # VFS FAT FS
@@ -240,6 +243,10 @@ MBEDTLS_CONFIG_FILE ?= \"mbedtls/mbedtls_config_port.h\"
GIT_SUBMODULES += $(MBEDTLS_DIR) GIT_SUBMODULES += $(MBEDTLS_DIR)
CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE) CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE)
CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include
ifeq ($(MICROPY_PY_SSL_ECDSA_SIGN_ALT),1)
CFLAGS_EXTMOD += -DMICROPY_PY_SSL_ECDSA_SIGN_ALT=1
LDFLAGS_EXTMOD += -Wl,--wrap=mbedtls_ecdsa_write_signature
endif
SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c
SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\
aes.c \ aes.c \
@@ -331,6 +338,8 @@ $(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address
SRC_THIRDPARTY_C += shared/netutils/netutils.c SRC_THIRDPARTY_C += shared/netutils/netutils.c
SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
apps/mdns/mdns.c \ apps/mdns/mdns.c \
apps/mdns/mdns_domain.c \
apps/mdns/mdns_out.c \
core/def.c \ core/def.c \
core/dns.c \ core/dns.c \
core/inet_chksum.c \ core/inet_chksum.c \
@@ -348,6 +357,7 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
core/tcp_out.c \ core/tcp_out.c \
core/timeouts.c \ core/timeouts.c \
core/udp.c \ core/udp.c \
core/ipv4/acd.c \
core/ipv4/autoip.c \ core/ipv4/autoip.c \
core/ipv4/dhcp.c \ core/ipv4/dhcp.c \
core/ipv4/etharp.c \ core/ipv4/etharp.c \
@@ -366,6 +376,32 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
core/ipv6/mld6.c \ core/ipv6/mld6.c \
core/ipv6/nd6.c \ core/ipv6/nd6.c \
netif/ethernet.c \ netif/ethernet.c \
netif/ppp/auth.c \
netif/ppp/ccp.c \
netif/ppp/chap-md5.c \
netif/ppp/chap_ms.c \
netif/ppp/chap-new.c \
netif/ppp/demand.c \
netif/ppp/eap.c \
netif/ppp/ecp.c \
netif/ppp/eui64.c \
netif/ppp/fsm.c \
netif/ppp/ipcp.c \
netif/ppp/ipv6cp.c \
netif/ppp/lcp.c \
netif/ppp/magic.c \
netif/ppp/mppe.c \
netif/ppp/multilink.c \
netif/ppp/polarssl/md5.c \
netif/ppp/pppapi.c \
netif/ppp/ppp.c \
netif/ppp/pppcrypt.c \
netif/ppp/pppoe.c \
netif/ppp/pppol2tp.c \
netif/ppp/pppos.c \
netif/ppp/upap.c \
netif/ppp/utils.c \
netif/ppp/vj.c \
) )
ifeq ($(MICROPY_PY_LWIP_LOOPBACK),1) ifeq ($(MICROPY_PY_LWIP_LOOPBACK),1)
CFLAGS_EXTMOD += -DLWIP_NETIF_LOOPBACK=1 CFLAGS_EXTMOD += -DLWIP_NETIF_LOOPBACK=1
@@ -526,6 +562,7 @@ ifeq ($(MICROPY_PY_OPENAMP),1)
OPENAMP_DIR = lib/open-amp OPENAMP_DIR = lib/open-amp
LIBMETAL_DIR = lib/libmetal LIBMETAL_DIR = lib/libmetal
GIT_SUBMODULES += $(LIBMETAL_DIR) $(OPENAMP_DIR) GIT_SUBMODULES += $(LIBMETAL_DIR) $(OPENAMP_DIR)
MICROPY_PY_OPENAMP_MODE ?= 0
include $(TOP)/extmod/libmetal/libmetal.mk include $(TOP)/extmod/libmetal/libmetal.mk
INC += -I$(TOP)/$(OPENAMP_DIR) INC += -I$(TOP)/$(OPENAMP_DIR)
@@ -535,12 +572,21 @@ ifeq ($(MICROPY_PY_OPENAMP_REMOTEPROC),1)
CFLAGS += -DMICROPY_PY_OPENAMP_REMOTEPROC=1 CFLAGS += -DMICROPY_PY_OPENAMP_REMOTEPROC=1
endif endif
ifeq ($(MICROPY_PY_OPENAMP_MODE),0)
CFLAGS += -DMICROPY_PY_OPENAMP_HOST=1
CFLAGS_THIRDPARTY += -DVIRTIO_DRIVER_ONLY
else ifeq ($(MICROPY_PY_OPENAMP_MODE),1)
CFLAGS += -DMICROPY_PY_OPENAMP_DEVICE=1
CFLAGS_THIRDPARTY += -DVIRTIO_DEVICE_ONLY
else
$(error Invalid Open-AMP mode specified: $(MICROPY_PY_OPENAMP_MODE))
endif
CFLAGS_THIRDPARTY += \ CFLAGS_THIRDPARTY += \
-I$(BUILD)/openamp \ -I$(BUILD)/openamp \
-I$(TOP)/$(OPENAMP_DIR) \ -I$(TOP)/$(OPENAMP_DIR) \
-I$(TOP)/$(OPENAMP_DIR)/lib/include/ \ -I$(TOP)/$(OPENAMP_DIR)/lib/include/ \
-DMETAL_INTERNAL \ -DMETAL_INTERNAL \
-DVIRTIO_DRIVER_ONLY \
-DNO_ATOMIC_64_SUPPORT \ -DNO_ATOMIC_64_SUPPORT \
-DRPMSG_BUFFER_SIZE=512 \ -DRPMSG_BUFFER_SIZE=512 \

View File

@@ -4,13 +4,13 @@
# This replicates the basic functionality of the pre-processor, including adding a "micropython" # This replicates the basic functionality of the pre-processor, including adding a "micropython"
# platform that is almost identical to the built-in "generic" platform with a few small changes # platform that is almost identical to the built-in "generic" platform with a few small changes
# provided by the files in extmod/libmetal. # provided by the files in extmod/libmetal.
$(BUILD)/openamp: $(BUILD) $(BUILD)/openamp: | $(BUILD)
$(MKDIR) -p $@ $(MKDIR) -p $@
$(BUILD)/openamp/metal: $(BUILD)/openamp $(BUILD)/openamp/metal: | $(BUILD)/openamp
$(MKDIR) -p $@ $(MKDIR) -p $@
$(BUILD)/openamp/metal/config.h: $(BUILD)/openamp/metal $(TOP)/$(LIBMETAL_DIR)/lib/config.h $(BUILD)/openamp/metal/config.h: $(TOP)/$(LIBMETAL_DIR)/lib/config.h | $(BUILD)/openamp/metal
@$(ECHO) "GEN $@" @$(ECHO) "GEN $@"
@for file in $(TOP)/$(LIBMETAL_DIR)/lib/*.c $(TOP)/$(LIBMETAL_DIR)/lib/*.h; do $(SED) -e "s/@PROJECT_SYSTEM@/micropython/g" -e "s/@PROJECT_PROCESSOR@/arm/g" $$file > $(BUILD)/openamp/metal/$$(basename $$file); done @for file in $(TOP)/$(LIBMETAL_DIR)/lib/*.c $(TOP)/$(LIBMETAL_DIR)/lib/*.h; do $(SED) -e "s/@PROJECT_SYSTEM@/micropython/g" -e "s/@PROJECT_PROCESSOR@/arm/g" $$file > $(BUILD)/openamp/metal/$$(basename $$file); done
$(MKDIR) -p $(BUILD)/openamp/metal/processor/arm $(MKDIR) -p $(BUILD)/openamp/metal/processor/arm
@@ -33,7 +33,6 @@ SRC_LIBMETAL_C := $(addprefix $(BUILD)/openamp/metal/,\
shmem.c \ shmem.c \
softirq.c \ softirq.c \
version.c \ version.c \
device.c \
system/micropython/condition.c \ system/micropython/condition.c \
system/micropython/device.c \ system/micropython/device.c \
system/micropython/io.c \ system/micropython/io.c \

View File

@@ -33,12 +33,6 @@
#include "extmod/modmachine.h" #include "extmod/modmachine.h"
// if a port didn't define MSB/LSB constants then provide them
#ifndef MICROPY_PY_MACHINE_SPI_MSB
#define MICROPY_PY_MACHINE_SPI_MSB (0)
#define MICROPY_PY_MACHINE_SPI_LSB (1)
#endif
/******************************************************************************/ /******************************************************************************/
// MicroPython bindings for generic machine.SPI // MicroPython bindings for generic machine.SPI
@@ -154,9 +148,9 @@ static uint32_t baudrate_to_delay_half(uint32_t baudrate) {
static void mp_machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { static void mp_machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u," mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u, firstbit=%u,"
" sck=" MP_HAL_PIN_FMT ", mosi=" MP_HAL_PIN_FMT ", miso=" MP_HAL_PIN_FMT ")", " sck=" MP_HAL_PIN_FMT ", mosi=" MP_HAL_PIN_FMT ", miso=" MP_HAL_PIN_FMT ")",
baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase, baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase, self->spi.firstbit,
mp_hal_pin_name(self->spi.sck), mp_hal_pin_name(self->spi.mosi), mp_hal_pin_name(self->spi.miso)); mp_hal_pin_name(self->spi.sck), mp_hal_pin_name(self->spi.mosi), mp_hal_pin_name(self->spi.miso));
} }
@@ -185,9 +179,7 @@ static mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
if (args[ARG_bits].u_int != 8) { if (args[ARG_bits].u_int != 8) {
mp_raise_ValueError(MP_ERROR_TEXT("bits must be 8")); mp_raise_ValueError(MP_ERROR_TEXT("bits must be 8"));
} }
if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) { self->spi.firstbit = args[ARG_firstbit].u_int;
mp_raise_ValueError(MP_ERROR_TEXT("firstbit must be MSB"));
}
if (args[ARG_sck].u_obj == MP_OBJ_NULL if (args[ARG_sck].u_obj == MP_OBJ_NULL
|| args[ARG_mosi].u_obj == MP_OBJ_NULL || args[ARG_mosi].u_obj == MP_OBJ_NULL
|| args[ARG_miso].u_obj == MP_OBJ_NULL) { || args[ARG_miso].u_obj == MP_OBJ_NULL) {
@@ -206,11 +198,12 @@ static mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t *)self_in; mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t *)self_in;
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso }; enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
@@ -227,6 +220,9 @@ static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, cons
if (args[ARG_phase].u_int != -1) { if (args[ARG_phase].u_int != -1) {
self->spi.phase = args[ARG_phase].u_int; self->spi.phase = args[ARG_phase].u_int;
} }
if (args[ARG_firstbit].u_int != -1) {
self->spi.firstbit = args[ARG_firstbit].u_int;
}
if (args[ARG_sck].u_obj != MP_OBJ_NULL) { if (args[ARG_sck].u_obj != MP_OBJ_NULL) {
self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj); self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
} }

View File

@@ -157,6 +157,11 @@ static mp_obj_t usb_device_active(size_t n_args, const mp_obj_t *args) {
} }
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(usb_device_active_obj, 1, 2, usb_device_active); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(usb_device_active_obj, 1, 2, usb_device_active);
static mp_obj_t usb_remote_wakeup(mp_obj_t self) {
return mp_obj_new_bool(tud_remote_wakeup());
}
static MP_DEFINE_CONST_FUN_OBJ_1(usb_remote_wakeup_obj, usb_remote_wakeup);
static mp_obj_t usb_device_stall(size_t n_args, const mp_obj_t *args) { static mp_obj_t usb_device_stall(size_t n_args, const mp_obj_t *args) {
mp_obj_usb_device_t *self = (mp_obj_usb_device_t *)MP_OBJ_TO_PTR(args[0]); mp_obj_usb_device_t *self = (mp_obj_usb_device_t *)MP_OBJ_TO_PTR(args[0]);
int epnum = mp_obj_get_int(args[1]); int epnum = mp_obj_get_int(args[1]);
@@ -272,6 +277,7 @@ static const mp_rom_map_elem_t usb_device_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_submit_xfer), MP_ROM_PTR(&usb_device_submit_xfer_obj) }, { MP_ROM_QSTR(MP_QSTR_submit_xfer), MP_ROM_PTR(&usb_device_submit_xfer_obj) },
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&usb_device_active_obj) }, { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&usb_device_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_stall), MP_ROM_PTR(&usb_device_stall_obj) }, { MP_ROM_QSTR(MP_QSTR_stall), MP_ROM_PTR(&usb_device_stall_obj) },
{ MP_ROM_QSTR(MP_QSTR_remote_wakeup), MP_ROM_PTR(&usb_remote_wakeup_obj) },
// Built-in driver constants // Built-in driver constants
{ MP_ROM_QSTR(MP_QSTR_BUILTIN_NONE), MP_ROM_PTR(&mp_type_usb_device_builtin_none) }, { MP_ROM_QSTR(MP_QSTR_BUILTIN_NONE), MP_ROM_PTR(&mp_type_usb_device_builtin_none) },

View File

@@ -0,0 +1,88 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright The Mbed TLS Contributors
* Copyright (c) 2024 Damien P. George
*
* This file provides default fallback functions for use with alternate
* cryptography functions implemented in Python.
*/
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
#if defined(MBEDTLS_ECP_RESTARTABLE) || defined(MBEDTLS_ECDSA_DETERMINISTIC)
#error "MICROPY_PY_SSL_ECDSA_SIGN_ALT cannot be used with MBEDTLS_ECP_RESTARTABLE or MBEDTLS_ECDSA_DETERMINISTIC"
#endif
#include <string.h>
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#include "mbedtls/platform.h"
#include "mbedtls/ssl.h"
#include "mbedtls/error.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/asn1write.h"
extern int micropy_mbedtls_ecdsa_sign_alt(const mbedtls_mpi *d, const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen);
// Compute and write signature
// See lib/mbedtls/library/ecdsa.c:688
//
// Note: To avoid duplicating a lot of code, MBEDTLS_ECDSA_SIGN_ALT is not defined,
// which allows the default mbedtls_ecdsa_sign to be used as a fallback function.
// However, mbedtls_ecdsa_sign cannot be wrapped because it is called internally
// within its object file, so we wrap mbedtls_ecdsa_read/write_signature instead.
int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng) {
(void)md_alg;
if (f_rng == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Check if curve is supported for ECDSA.
if (!mbedtls_ecdsa_can_do(ctx->grp.id) || ctx->grp.N.p == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Try signing with the alternative function first.
int ret = micropy_mbedtls_ecdsa_sign_alt(&ctx->d, hash, hlen, sig, sig_size, slen);
// Fallback to the default mbedtls implementation if needed.
if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) {
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
size_t len = 0;
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
unsigned char *p = buf + sizeof(buf);
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_mpi(&p, buf, &s));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_mpi(&p, buf, &r));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
if (len > sig_size) {
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
} else {
ret = 0;
*slen = len;
memcpy(sig, p, len);
}
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
}
return ret;
}
#endif

View File

@@ -46,6 +46,7 @@
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_ECP_DP_SECP256K1_ENABLED
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#define MBEDTLS_CAN_ECDH #define MBEDTLS_CAN_ECDH
#define MBEDTLS_PK_CAN_ECDSA_SIGN #define MBEDTLS_PK_CAN_ECDSA_SIGN
#define MBEDTLS_PKCS1_V15 #define MBEDTLS_PKCS1_V15
@@ -72,6 +73,7 @@
#define MBEDTLS_ECP_C #define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C #define MBEDTLS_ENTROPY_C
#define MBEDTLS_ERROR_C #define MBEDTLS_ERROR_C
#define MBEDTLS_GCM_C
#define MBEDTLS_MD_C #define MBEDTLS_MD_C
#define MBEDTLS_MD5_C #define MBEDTLS_MD5_C
#define MBEDTLS_OID_C #define MBEDTLS_OID_C

View File

@@ -53,6 +53,9 @@ typedef struct _mp_obj_task_t {
typedef struct _mp_obj_task_queue_t { typedef struct _mp_obj_task_queue_t {
mp_obj_base_t base; mp_obj_base_t base;
mp_obj_task_t *heap; mp_obj_task_t *heap;
#if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK
mp_obj_t push_callback;
#endif
} mp_obj_task_queue_t; } mp_obj_task_queue_t;
static const mp_obj_type_t task_queue_type; static const mp_obj_type_t task_queue_type;
@@ -86,9 +89,16 @@ static int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
static mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { static mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
(void)args; (void)args;
mp_arg_check_num(n_args, n_kw, 0, 0, false); mp_arg_check_num(n_args, n_kw, 0, MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK ? 1 : 0, false);
mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type); mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type);
self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt); self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt);
#if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK
if (n_args == 1) {
self->push_callback = args[0];
} else {
self->push_callback = MP_OBJ_NULL;
}
#endif
return MP_OBJ_FROM_PTR(self); return MP_OBJ_FROM_PTR(self);
} }
@@ -113,6 +123,11 @@ static mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) {
task->ph_key = args[2]; task->ph_key = args[2];
} }
self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task)); self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task));
#if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK
if (self->push_callback != MP_OBJ_NULL) {
mp_call_function_1(self->push_callback, MP_OBJ_NEW_SMALL_INT(0));
}
#endif
return mp_const_none; return mp_const_none;
} }
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push);

View File

@@ -89,6 +89,12 @@ void __dbpanic(DB *db) {
mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db); mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db);
} }
static void check_btree_is_open(mp_obj_btree_t *self) {
if (!self->db) {
mp_raise_ValueError(MP_ERROR_TEXT("database closed"));
}
}
static mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) { static mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type); mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type);
o->stream = stream; o->stream = stream;
@@ -114,19 +120,28 @@ static void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind
static mp_obj_t btree_flush(mp_obj_t self_in) { static mp_obj_t btree_flush(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0)); return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0));
} }
static MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush); static MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush);
static mp_obj_t btree_close(mp_obj_t self_in) { static mp_obj_t btree_close(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(__bt_close(self->db)); int res;
if (self->db) {
res = __bt_close(self->db);
self->db = NULL;
} else {
res = RET_SUCCESS; // Closing an already-closed DB always succeeds.
}
return MP_OBJ_NEW_SMALL_INT(res);
} }
static MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close); static MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close);
static mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) { static mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
(void)n_args; (void)n_args;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
DBT key, val; DBT key, val;
buf_to_dbt(args[1], &key); buf_to_dbt(args[1], &key);
buf_to_dbt(args[2], &val); buf_to_dbt(args[2], &val);
@@ -136,6 +151,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
static mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) { static mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
DBT key, val; DBT key, val;
buf_to_dbt(args[1], &key); buf_to_dbt(args[1], &key);
int res = __bt_get(self->db, &key, &val, 0); int res = __bt_get(self->db, &key, &val, 0);
@@ -153,6 +169,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_get_obj, 2, 3, btree_get);
static mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) { static mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
check_btree_is_open(self);
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]); int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
DBT key, val; DBT key, val;
if (n_args > 2) { if (n_args > 2) {
@@ -225,6 +242,7 @@ static mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
static mp_obj_t btree_iternext(mp_obj_t self_in) { static mp_obj_t btree_iternext(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
DBT key, val; DBT key, val;
int res; int res;
bool desc = self->flags & FLAG_DESC; bool desc = self->flags & FLAG_DESC;
@@ -281,6 +299,7 @@ static mp_obj_t btree_iternext(mp_obj_t self_in) {
static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
check_btree_is_open(self);
if (value == MP_OBJ_NULL) { if (value == MP_OBJ_NULL) {
// delete // delete
DBT key; DBT key;
@@ -314,6 +333,7 @@ static mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
static mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { static mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in); mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
check_btree_is_open(self);
switch (op) { switch (op) {
case MP_BINARY_OP_CONTAINS: { case MP_BINARY_OP_CONTAINS: {
DBT key, val; DBT key, val;

View File

@@ -282,23 +282,29 @@ static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
mp_raise_ValueError(NULL); mp_raise_ValueError(NULL);
} }
size_t height_required = height;
size_t bpp = 1; size_t bpp = 1;
size_t height_required = height;
size_t width_required = width;
size_t strides_required = height - 1;
switch (format) { switch (format) {
case FRAMEBUF_MVLSB: case FRAMEBUF_MVLSB:
height_required = (height + 7) & ~7; height_required = (height + 7) & ~7;
strides_required = height_required - 8;
break; break;
case FRAMEBUF_MHLSB: case FRAMEBUF_MHLSB:
case FRAMEBUF_MHMSB: case FRAMEBUF_MHMSB:
stride = (stride + 7) & ~7; stride = (stride + 7) & ~7;
width_required = (width + 7) & ~7;
break; break;
case FRAMEBUF_GS2_HMSB: case FRAMEBUF_GS2_HMSB:
stride = (stride + 3) & ~3; stride = (stride + 3) & ~3;
width_required = (width + 3) & ~3;
bpp = 2; bpp = 2;
break; break;
case FRAMEBUF_GS4_HMSB: case FRAMEBUF_GS4_HMSB:
stride = (stride + 1) & ~1; stride = (stride + 1) & ~1;
width_required = (width + 1) & ~1;
bpp = 4; bpp = 4;
break; break;
case FRAMEBUF_GS8: case FRAMEBUF_GS8:
@@ -314,7 +320,7 @@ static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE); mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
if (height_required * stride * bpp / 8 > bufinfo.len) { if ((strides_required * stride + (height_required - strides_required) * width_required) * bpp / 8 > bufinfo.len) {
mp_raise_ValueError(NULL); mp_raise_ValueError(NULL);
} }
@@ -530,6 +536,10 @@ static mp_obj_t framebuf_ellipse(size_t n_args, const mp_obj_t *args_in) {
} else { } else {
mask |= ELLIPSE_MASK_ALL; mask |= ELLIPSE_MASK_ALL;
} }
if (args[2] == 0 && args[3] == 0) {
setpixel_checked(self, args[0], args[1], args[4], mask & ELLIPSE_MASK_ALL);
return mp_const_none;
}
mp_int_t two_asquare = 2 * args[2] * args[2]; mp_int_t two_asquare = 2 * args[2] * args[2];
mp_int_t two_bsquare = 2 * args[3] * args[3]; mp_int_t two_bsquare = 2 * args[3] * args[3];
mp_int_t x = args[2]; mp_int_t x = args[2];

View File

@@ -127,15 +127,15 @@ sio_fd_t sio_open(u8_t dvnum) {
} }
void sio_send(u8_t c, sio_fd_t fd) { void sio_send(u8_t c, sio_fd_t fd) {
mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream)); const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(lwip_slip_stream));
int error; int error;
type->stream_p->write(MP_STATE_VM(lwip_slip_stream), &c, 1, &error); stream_p->write(MP_STATE_VM(lwip_slip_stream), &c, 1, &error);
} }
u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len) { u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len) {
mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream)); const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(lwip_slip_stream));
int error; int error;
mp_uint_t out_sz = type->stream_p->read(MP_STATE_VM(lwip_slip_stream), data, len, &error); mp_uint_t out_sz = stream_p->read(MP_STATE_VM(lwip_slip_stream), data, len, &error);
if (out_sz == MP_STREAM_ERROR) { if (out_sz == MP_STREAM_ERROR) {
if (mp_is_nonblocking_error(error)) { if (mp_is_nonblocking_error(error)) {
return 0; return 0;
@@ -326,6 +326,10 @@ typedef struct _lwip_socket_obj_t {
int8_t state; int8_t state;
} lwip_socket_obj_t; } lwip_socket_obj_t;
static inline bool socket_is_timedout(lwip_socket_obj_t *socket, mp_uint_t ticks_start) {
return socket->timeout != -1 && (mp_uint_t)(mp_hal_ticks_ms() - ticks_start) >= socket->timeout;
}
static inline void poll_sockets(void) { static inline void poll_sockets(void) {
mp_event_wait_ms(1); mp_event_wait_ms(1);
} }
@@ -369,7 +373,7 @@ mp_obj_t lwip_format_inet_addr(const ip_addr_t *ip, mp_uint_t port) {
char ipstr[IPADDR_STRLEN_MAX]; char ipstr[IPADDR_STRLEN_MAX];
ipaddr_ntoa_r(ip, ipstr, sizeof(ipstr)); ipaddr_ntoa_r(ip, ipstr, sizeof(ipstr));
mp_obj_t tuple[2] = { mp_obj_t tuple[2] = {
tuple[0] = mp_obj_new_str(ipstr, strlen(ipstr)), tuple[0] = mp_obj_new_str_from_cstr(ipstr),
tuple[1] = mp_obj_new_int(port), tuple[1] = mp_obj_new_int(port),
}; };
return mp_obj_new_tuple(2, tuple); return mp_obj_new_tuple(2, tuple);
@@ -1036,26 +1040,22 @@ static mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
// accept incoming connection // accept incoming connection
struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget]; struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget];
if (*incoming_connection == NULL) { if (*incoming_connection == NULL) {
if (socket->timeout == 0) { mp_uint_t ticks_start = mp_hal_ticks_ms();
for (;;) {
MICROPY_PY_LWIP_EXIT MICROPY_PY_LWIP_EXIT
m_del_obj(lwip_socket_obj_t, socket2); poll_sockets();
mp_raise_OSError(MP_EAGAIN); MICROPY_PY_LWIP_REENTER
} else if (socket->timeout != -1) { if (*incoming_connection != NULL) {
mp_uint_t retries = socket->timeout / 100; break;
while (*incoming_connection == NULL) { }
if (socket_is_timedout(socket, ticks_start)) {
MICROPY_PY_LWIP_EXIT MICROPY_PY_LWIP_EXIT
if (retries-- == 0) { m_del_obj(lwip_socket_obj_t, socket2);
m_del_obj(lwip_socket_obj_t, socket2); if (socket->timeout == 0) {
mp_raise_OSError(MP_EAGAIN);
} else {
mp_raise_OSError(MP_ETIMEDOUT); mp_raise_OSError(MP_ETIMEDOUT);
} }
mp_hal_delay_ms(100);
MICROPY_PY_LWIP_REENTER
}
} else {
while (*incoming_connection == NULL) {
MICROPY_PY_LWIP_EXIT
poll_sockets();
MICROPY_PY_LWIP_REENTER
} }
} }
} }
@@ -1130,21 +1130,21 @@ static mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
MICROPY_PY_LWIP_EXIT MICROPY_PY_LWIP_EXIT
// And now we wait... // And now we wait...
if (socket->timeout != -1) { mp_uint_t ticks_start = mp_hal_ticks_ms();
for (mp_uint_t retries = socket->timeout / 100; retries--;) { for (;;) {
mp_hal_delay_ms(100); poll_sockets();
if (socket->state != STATE_CONNECTING) { if (socket->state != STATE_CONNECTING) {
break; break;
}
if (socket_is_timedout(socket, ticks_start)) {
if (socket->timeout == 0) {
mp_raise_OSError(MP_EINPROGRESS);
} else {
mp_raise_OSError(MP_ETIMEDOUT);
} }
} }
if (socket->state == STATE_CONNECTING) {
mp_raise_OSError(MP_EINPROGRESS);
}
} else {
while (socket->state == STATE_CONNECTING) {
poll_sockets();
}
} }
if (socket->state == STATE_CONNECTED) { if (socket->state == STATE_CONNECTED) {
err = ERR_OK; err = ERR_OK;
} else { } else {
@@ -1432,7 +1432,7 @@ static mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
case IP_DROP_MEMBERSHIP: { case IP_DROP_MEMBERSHIP: {
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != sizeof(ip_addr_t) * 2) { if (bufinfo.len != sizeof(MP_IGMP_IP_ADDR_TYPE) * 2) {
mp_raise_ValueError(NULL); mp_raise_ValueError(NULL);
} }

View File

@@ -24,6 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "py/builtin.h"
#include "py/runtime.h" #include "py/runtime.h"
#if MICROPY_PY_MACHINE #if MICROPY_PY_MACHINE
@@ -35,6 +36,10 @@
#include "drivers/dht/dht.h" #include "drivers/dht/dht.h"
#endif #endif
#if !MICROPY_PY_SYS_EXIT
#error MICROPY_PY_MACHINE requires MICROPY_PY_SYS_EXIT
#endif
// The port must provide implementations of these low-level machine functions. // The port must provide implementations of these low-level machine functions.
static void mp_machine_idle(void); static void mp_machine_idle(void);
@@ -61,12 +66,6 @@ NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args);
#include MICROPY_PY_MACHINE_INCLUDEFILE #include MICROPY_PY_MACHINE_INCLUDEFILE
#endif #endif
static mp_obj_t machine_soft_reset(void) {
pyexec_system_exit = PYEXEC_FORCED_EXIT;
mp_raise_type(&mp_type_SystemExit);
}
static MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
#if MICROPY_PY_MACHINE_BOOTLOADER #if MICROPY_PY_MACHINE_BOOTLOADER
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
mp_machine_bootloader(n_args, args); mp_machine_bootloader(n_args, args);
@@ -109,7 +108,7 @@ static mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
return mp_const_none; return mp_const_none;
} }
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, MICROPY_PY_MACHINE_FREQ_NUM_ARGS_MAX, machine_freq);
static mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { static mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
mp_machine_lightsleep(n_args, args); mp_machine_lightsleep(n_args, args);
@@ -157,7 +156,7 @@ static const mp_rom_map_elem_t machine_module_globals_table[] = {
#endif #endif
// Reset related functions. // Reset related functions.
{ MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&mp_sys_exit_obj) },
#if MICROPY_PY_MACHINE_BOOTLOADER #if MICROPY_PY_MACHINE_BOOTLOADER
{ MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
#endif #endif

View File

@@ -127,7 +127,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj, 0, 1, network_count
mp_obj_t mod_network_hostname(size_t n_args, const mp_obj_t *args) { mp_obj_t mod_network_hostname(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) { if (n_args == 0) {
return mp_obj_new_str(mod_network_hostname_data, strlen(mod_network_hostname_data)); return mp_obj_new_str_from_cstr(mod_network_hostname_data);
} else { } else {
size_t len; size_t len;
const char *str = mp_obj_str_get_data(args[0], &len); const char *str = mp_obj_str_get_data(args[0], &len);
@@ -144,15 +144,22 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_hostname_obj, 0, 1, mod_n
#if LWIP_VERSION_MAJOR >= 2 #if LWIP_VERSION_MAJOR >= 2
MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, mod_network_ipconfig); MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, mod_network_ipconfig);
#endif #endif
#if MICROPY_PY_NETWORK_NINAW10
MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, network_ninaw10_ipconfig);
#endif
static const mp_rom_map_elem_t mp_module_network_globals_table[] = { static const mp_rom_map_elem_t mp_module_network_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
{ MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) }, { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) },
{ MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mod_network_hostname_obj) }, { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mod_network_hostname_obj) },
#if LWIP_VERSION_MAJOR >= 2 #if LWIP_VERSION_MAJOR >= 2 || MICROPY_PY_NETWORK_NINAW10
{ MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&mod_network_ipconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&mod_network_ipconfig_obj) },
#endif #endif
#if MICROPY_PY_NETWORK_PPP_LWIP
{ MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&mp_network_ppp_lwip_type) },
#endif
// Defined per port in mpconfigport.h // Defined per port in mpconfigport.h
#ifdef MICROPY_PORT_NETWORK_INTERFACES #ifdef MICROPY_PORT_NETWORK_INTERFACES
{ MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },

View File

@@ -72,6 +72,10 @@ mp_obj_t mod_network_hostname(size_t n_args, const mp_obj_t *args);
#include "lwip/init.h" #include "lwip/init.h"
#if MICROPY_PY_NETWORK_PPP_LWIP
extern const struct _mp_obj_type_t mp_network_ppp_lwip_type;
#endif
struct netif; struct netif;
void mod_network_lwip_init(void); void mod_network_lwip_init(void);
void mod_network_lwip_poll_wrapper(uint32_t ticks_ms); void mod_network_lwip_poll_wrapper(uint32_t ticks_ms);
@@ -83,6 +87,10 @@ extern int mp_mod_network_prefer_dns_use_ip_version;
#endif #endif
#elif defined(MICROPY_PORT_NETWORK_INTERFACES) #elif defined(MICROPY_PORT_NETWORK_INTERFACES)
#if MICROPY_PY_NETWORK_NINAW10
mp_obj_t network_ninaw10_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
#endif
struct _mod_network_socket_obj_t; struct _mod_network_socket_obj_t;
typedef struct _mod_network_nic_protocol_t { typedef struct _mod_network_nic_protocol_t {

View File

@@ -52,11 +52,20 @@
#if MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #if MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
#define VIRTIO_DEV_ID 0xFF #define VIRTIO_DEV_ID 0xFF
#if MICROPY_PY_OPENAMP_HOST
#define VIRTIO_DEV_ROLE RPMSG_HOST
#else
#define VIRTIO_DEV_ROLE RPMSG_REMOTE
#endif // MICROPY_PY_OPENAMP_HOST
#define VIRTIO_DEV_FEATURES (1 << VIRTIO_RPMSG_F_NS) #define VIRTIO_DEV_FEATURES (1 << VIRTIO_RPMSG_F_NS)
#define VRING0_ID 0 // VRING0 ID (host to remote) fixed to 0 for linux compatibility #define VRING0_ID 0 // VRING0 ID (host to remote) fixed to 0 for linux compatibility
#define VRING1_ID 1 // VRING1 ID (remote to host) fixed to 1 for linux compatibility #define VRING1_ID 1 // VRING1 ID (remote to host) fixed to 1 for linux compatibility
#if MICROPY_PY_OPENAMP_HOST
#define VRING_NOTIFY_ID VRING0_ID #define VRING_NOTIFY_ID VRING0_ID
#else
#define VRING_NOTIFY_ID VRING1_ID
#endif // MICROPY_PY_OPENAMP_HOST
#define VRING_COUNT 2 #define VRING_COUNT 2
#define VRING_ALIGNMENT 32 #define VRING_ALIGNMENT 32
@@ -71,13 +80,15 @@
#define VRING_BUFF_ADDR (METAL_SHM_ADDR + 0x2000) #define VRING_BUFF_ADDR (METAL_SHM_ADDR + 0x2000)
#define VRING_BUFF_SIZE (METAL_SHM_SIZE - 0x2000) #define VRING_BUFF_SIZE (METAL_SHM_SIZE - 0x2000)
#if MICROPY_PY_OPENAMP_HOST
static const char openamp_trace_buf[128]; static const char openamp_trace_buf[128];
#define MICROPY_PY_OPENAMP_TRACE_BUF ((uint32_t)openamp_trace_buf) #define MICROPY_PY_OPENAMP_TRACE_BUF ((uint32_t)openamp_trace_buf)
#define MICROPY_PY_OPENAMP_TRACE_BUF_LEN sizeof(MICROPY_PY_OPENAMP_TRACE_BUF) #define MICROPY_PY_OPENAMP_TRACE_BUF_LEN sizeof(MICROPY_PY_OPENAMP_TRACE_BUF)
#endif // MICROPY_PY_OPENAMP_HOST
#endif // MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #endif // MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
#if MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC
extern mp_obj_type_t openamp_remoteproc_type; extern mp_obj_type_t openamp_remoteproc_type;
#endif #endif
@@ -181,13 +192,13 @@ static mp_obj_t endpoint_send(uint n_args, const mp_obj_t *pos_args, mp_map_t *k
for (mp_uint_t start = mp_hal_ticks_ms(); ;) { for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
bytes = rpmsg_send_offchannel_raw(&self->ep, src, dest, rbuf.buf, rbuf.len, false); bytes = rpmsg_send_offchannel_raw(&self->ep, src, dest, rbuf.buf, rbuf.len, false);
if (bytes > 0 || timeout == 0) { if (bytes > 0 || timeout == 0) {
MICROPY_EVENT_POLL_HOOK mp_event_handle_nowait();
break; break;
} }
if (timeout > 0 && (mp_hal_ticks_ms() - start > timeout)) { if (timeout > 0 && (mp_hal_ticks_ms() - start > timeout)) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for a free buffer")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for a free buffer"));
} }
MICROPY_EVENT_POLL_HOOK mp_event_wait_ms(1);
} }
return mp_obj_new_int(bytes); return mp_obj_new_int(bytes);
} }
@@ -210,7 +221,7 @@ static mp_obj_t endpoint_make_new(const mp_obj_type_t *type, size_t n_args, size
enum { ARG_name, ARG_callback, ARG_src, ARG_dest }; enum { ARG_name, ARG_callback, ARG_src, ARG_dest };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_name, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE } }, { MP_QSTR_name, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE } },
{ MP_QSTR_callback, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE } }, { MP_QSTR_callback, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE } },
{ MP_QSTR_src, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } }, { MP_QSTR_src, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } },
{ MP_QSTR_dest, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } }, { MP_QSTR_dest, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = RPMSG_ADDR_ANY } },
}; };
@@ -263,16 +274,15 @@ static void openamp_ns_callback(struct rpmsg_device *rdev, const char *name, uin
// the Name Service (NS) announcement containing the name of the channel. // the Name Service (NS) announcement containing the name of the channel.
virtio_dev_obj_t *virtio_device = metal_container_of(rdev, virtio_dev_obj_t, rvdev); virtio_dev_obj_t *virtio_device = metal_container_of(rdev, virtio_dev_obj_t, rvdev);
if (virtio_device->ns_callback != mp_const_none) { if (virtio_device->ns_callback != mp_const_none) {
mp_call_function_2(virtio_device->ns_callback, mp_obj_new_int(dest), mp_obj_new_str(name, strlen(name))); mp_call_function_2(virtio_device->ns_callback, mp_obj_new_int(dest), mp_obj_new_str_from_cstr(name));
} }
} }
#if MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
// The shared resource table must be initialized manually by the host here, // The shared resource table must be initialized manually by the host here,
// because it's not located in the data region, so the startup code doesn't // because it's not located in the data region, so the startup code doesn't
// know about it. // know about it.
static void openamp_rsc_table_init(openamp_rsc_table_t **rsc_table_out) { static void openamp_rsc_table_init(openamp_rsc_table_t *rsc_table) {
openamp_rsc_table_t *rsc_table = METAL_RSC_ADDR;
memset(rsc_table, 0, METAL_RSC_SIZE); memset(rsc_table, 0, METAL_RSC_SIZE);
rsc_table->version = 1; rsc_table->version = 1;
@@ -299,9 +309,8 @@ static void openamp_rsc_table_init(openamp_rsc_table_t **rsc_table_out) {
// Flush resource table. // Flush resource table.
metal_cache_flush((uint32_t *)rsc_table, sizeof(openamp_rsc_table_t)); metal_cache_flush((uint32_t *)rsc_table, sizeof(openamp_rsc_table_t));
#endif #endif
*rsc_table_out = rsc_table;
} }
#endif // MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE #endif // MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_RSC_TABLE_ENABLE
static mp_obj_t openamp_new_service_callback(mp_obj_t ns_callback) { static mp_obj_t openamp_new_service_callback(mp_obj_t ns_callback) {
if (MP_STATE_PORT(virtio_device) == NULL) { if (MP_STATE_PORT(virtio_device) == NULL) {
@@ -342,8 +351,10 @@ void openamp_init(void) {
metal_init(&metal_params); metal_init(&metal_params);
// Initialize the shared resource table. // Initialize the shared resource table.
openamp_rsc_table_t *rsc_table; openamp_rsc_table_t *rsc_table = METAL_RSC_ADDR;
openamp_rsc_table_init(&rsc_table); #if MICROPY_PY_OPENAMP_HOST
openamp_rsc_table_init(rsc_table);
#endif // MICROPY_PY_OPENAMP_HOST
if (metal_register_generic_device(&shm_device) != 0) { if (metal_register_generic_device(&shm_device) != 0) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to register metal device")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to register metal device"));
@@ -368,7 +379,7 @@ void openamp_init(void) {
} }
// Create virtio device. // Create virtio device.
struct virtio_device *vdev = rproc_virtio_create_vdev(RPMSG_HOST, VIRTIO_DEV_ID, struct virtio_device *vdev = rproc_virtio_create_vdev(VIRTIO_DEV_ROLE, VIRTIO_DEV_ID,
&rsc_table->vdev, rsc_io, NULL, metal_rproc_notify, NULL); &rsc_table->vdev, rsc_io, NULL, metal_rproc_notify, NULL);
if (vdev == NULL) { if (vdev == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to create virtio device")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to create virtio device"));
@@ -389,8 +400,8 @@ void openamp_init(void) {
// The remote processor detects that the virtio device is ready by polling // The remote processor detects that the virtio device is ready by polling
// the status field in the resource table. // the status field in the resource table.
rpmsg_virtio_init_shm_pool(&virtio_device->shm_pool, (void *)VRING_BUFF_ADDR, (size_t)VRING_BUFF_SIZE); rpmsg_virtio_init_shm_pool(&virtio_device->shm_pool, (void *)VRING_BUFF_ADDR, (size_t)VRING_BUFF_SIZE);
rpmsg_init_vdev(&virtio_device->rvdev, vdev, openamp_ns_callback, shm_io, &virtio_device->shm_pool);
rpmsg_init_vdev(&virtio_device->rvdev, vdev, openamp_ns_callback, shm_io, &virtio_device->shm_pool);
MP_STATE_PORT(virtio_device) = virtio_device; MP_STATE_PORT(virtio_device) = virtio_device;
} }
@@ -399,7 +410,7 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ENDPOINT_ADDR_ANY), MP_ROM_INT(RPMSG_ADDR_ANY) }, { MP_ROM_QSTR(MP_QSTR_ENDPOINT_ADDR_ANY), MP_ROM_INT(RPMSG_ADDR_ANY) },
{ MP_ROM_QSTR(MP_QSTR_new_service_callback), MP_ROM_PTR(&openamp_new_service_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_new_service_callback), MP_ROM_PTR(&openamp_new_service_callback_obj) },
{ MP_ROM_QSTR(MP_QSTR_Endpoint), MP_ROM_PTR(&endpoint_type) }, { MP_ROM_QSTR(MP_QSTR_Endpoint), MP_ROM_PTR(&endpoint_type) },
#if MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC
{ MP_ROM_QSTR(MP_QSTR_RemoteProc), MP_ROM_PTR(&openamp_remoteproc_type) }, { MP_ROM_QSTR(MP_QSTR_RemoteProc), MP_ROM_PTR(&openamp_remoteproc_type) },
#endif #endif
}; };

View File

@@ -26,7 +26,7 @@
* OpenAMP's remoteproc class. * OpenAMP's remoteproc class.
*/ */
#if MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC
#include "py/obj.h" #include "py/obj.h"
#include "py/nlr.h" #include "py/nlr.h"
@@ -137,7 +137,7 @@ mp_obj_t openamp_remoteproc_make_new(const mp_obj_type_t *type, size_t n_args, s
} }
if (mp_obj_is_int(args[ARG_entry].u_obj)) { if (mp_obj_is_int(args[ARG_entry].u_obj)) {
self->rproc.bootaddr = mp_obj_get_int(args[ARG_entry].u_obj); self->rproc.bootaddr = mp_obj_int_get_truncated(args[ARG_entry].u_obj);
} else { } else {
#if MICROPY_PY_OPENAMP_REMOTEPROC_ELFLD_ENABLE #if MICROPY_PY_OPENAMP_REMOTEPROC_ELFLD_ENABLE
// Load firmware. // Load firmware.
@@ -170,4 +170,4 @@ MP_DEFINE_CONST_OBJ_TYPE(
locals_dict, &openamp_remoteproc_dict locals_dict, &openamp_remoteproc_dict
); );
#endif // MICROPY_PY_OPENAMP_REMOTEPROC #endif // MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC

View File

@@ -26,7 +26,7 @@
* OpenAMP's remoteproc store. * OpenAMP's remoteproc store.
*/ */
#if MICROPY_PY_OPENAMP_REMOTEPROC #if MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC
#include "py/obj.h" #include "py/obj.h"
#include "py/nlr.h" #include "py/nlr.h"
@@ -70,7 +70,7 @@ void *mp_openamp_remoteproc_store_alloc(void) {
static int openamp_remoteproc_store_open(void *store, const char *path, const void **image_data) { static int openamp_remoteproc_store_open(void *store, const char *path, const void **image_data) {
metal_log(METAL_LOG_DEBUG, "store_open(): %s\n", path); metal_log(METAL_LOG_DEBUG, "store_open(): %s\n", path);
mp_obj_t args[2] = { mp_obj_t args[2] = {
mp_obj_new_str(path, strlen(path)), mp_obj_new_str_from_cstr(path),
MP_OBJ_NEW_QSTR(MP_QSTR_rb), MP_OBJ_NEW_QSTR(MP_QSTR_rb),
}; };
@@ -141,4 +141,4 @@ const struct image_store_ops openamp_remoteproc_store_ops = {
#endif // MICROPY_PY_OPENAMP_REMOTEPROC_STORE_ENABLE #endif // MICROPY_PY_OPENAMP_REMOTEPROC_STORE_ENABLE
#endif // MICROPY_PY_OPENAMP_REMOTEPROC #endif // MICROPY_PY_OPENAMP_HOST && MICROPY_PY_OPENAMP_REMOTEPROC

View File

@@ -153,9 +153,6 @@ static const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_os_putenv_obj) }, { MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_os_putenv_obj) },
{ MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_os_unsetenv_obj) }, { MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_os_unsetenv_obj) },
#endif #endif
#if MICROPY_PY_OS_SEP
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
#endif
#if MICROPY_PY_OS_SYNC #if MICROPY_PY_OS_SYNC
{ MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_os_sync_obj) }, { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_os_sync_obj) },
#endif #endif
@@ -170,6 +167,7 @@ static const mp_rom_map_elem_t os_module_globals_table[] = {
#endif #endif
#if MICROPY_VFS #if MICROPY_VFS
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },

View File

@@ -83,6 +83,9 @@
#elif defined(__NEWLIB__) #elif defined(__NEWLIB__)
#define MICROPY_PLATFORM_LIBC_LIB "newlib" #define MICROPY_PLATFORM_LIBC_LIB "newlib"
#define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION #define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION
#elif defined(_PICOLIBC__)
#define MICROPY_PLATFORM_LIBC_LIB "picolibc"
#define MICROPY_PLATFORM_LIBC_VER _PICOLIBC_VERSION
#else #else
#define MICROPY_PLATFORM_LIBC_LIB "" #define MICROPY_PLATFORM_LIBC_LIB ""
#define MICROPY_PLATFORM_LIBC_VER "" #define MICROPY_PLATFORM_LIBC_VER ""

View File

@@ -31,7 +31,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/binary.h" #include "py/binary.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/stackctrl.h" #include "py/cstack.h"
#if MICROPY_PY_BUILTINS_STR_UNICODE #if MICROPY_PY_BUILTINS_STR_UNICODE
#include "py/unicode.h" #include "py/unicode.h"
@@ -39,7 +39,7 @@
#if MICROPY_PY_RE #if MICROPY_PY_RE
#define re1_5_stack_chk() MP_STACK_CHECK() #define re1_5_stack_chk() mp_cstack_check()
#include "lib/re1.5/re1.5.h" #include "lib/re1.5/re1.5.h"
@@ -194,7 +194,8 @@ static void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
mp_printf(print, "<re %p>", self); mp_printf(print, "<re %p>", self);
} }
static mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { // Note: this function can't be named re_exec because it may clash with system headers, eg on FreeBSD
static mp_obj_t re_exec_helper(bool is_anchored, uint n_args, const mp_obj_t *args) {
(void)n_args; (void)n_args;
mp_obj_re_t *self; mp_obj_re_t *self;
if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) {
@@ -223,12 +224,12 @@ static mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
} }
static mp_obj_t re_match(size_t n_args, const mp_obj_t *args) { static mp_obj_t re_match(size_t n_args, const mp_obj_t *args) {
return re_exec(true, n_args, args); return re_exec_helper(true, n_args, args);
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match);
static mp_obj_t re_search(size_t n_args, const mp_obj_t *args) { static mp_obj_t re_search(size_t n_args, const mp_obj_t *args) {
return re_exec(false, n_args, args); return re_exec_helper(false, n_args, args);
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);

View File

@@ -53,6 +53,10 @@
#else #else
#include "mbedtls/version.h" #include "mbedtls/version.h"
#endif #endif
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
#include "mbedtls/ecdsa.h"
#include "mbedtls/asn1.h"
#endif
#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR) #define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
@@ -68,6 +72,9 @@ typedef struct _mp_obj_ssl_context_t {
int authmode; int authmode;
int *ciphersuites; int *ciphersuites;
mp_obj_t handler; mp_obj_t handler;
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
mp_obj_t ecdsa_sign_callback;
#endif
} mp_obj_ssl_context_t; } mp_obj_ssl_context_t;
// This corresponds to an SSLSocket object. // This corresponds to an SSLSocket object.
@@ -100,6 +107,23 @@ static void mbedtls_debug(void *ctx, int level, const char *file, int line, cons
} }
#endif #endif
// Given a string-like object holding PEM or DER formatted ASN.1 data, return a
// pointer to its buffer and the correct length for mbedTLS APIs.
//
// (mbedTLS >= 3.5 rejects DER formatted data with trailing bytes within keylen,
// but PEM must include a terminating NUL byte in the keylen...)
static const unsigned char *asn1_get_data(mp_obj_t obj, size_t *out_len) {
size_t len;
const char *str = mp_obj_str_get_data(obj, &len);
#if defined(MBEDTLS_PEM_PARSE_C)
if (strstr(str, "-----BEGIN ") != NULL) {
++len;
}
#endif
*out_len = len;
return (const unsigned char *)str;
}
static NORETURN void mbedtls_raise_error(int err) { static NORETURN void mbedtls_raise_error(int err) {
// Handle special cases. // Handle special cases.
if (err == MBEDTLS_ERR_SSL_ALLOC_FAILED) { if (err == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
@@ -149,6 +173,13 @@ static NORETURN void mbedtls_raise_error(int err) {
#endif #endif
} }
// Stores the current SSLContext for use in mbedtls callbacks where the current state is not passed.
static inline void store_active_context(mp_obj_ssl_context_t *ssl_context) {
#if MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT
MP_STATE_THREAD(tls_ssl_context) = ssl_context;
#endif
}
static void ssl_check_async_handshake_failure(mp_obj_ssl_socket_t *sslsock, int *errcode) { static void ssl_check_async_handshake_failure(mp_obj_ssl_socket_t *sslsock, int *errcode) {
if ( if (
#if MBEDTLS_VERSION_NUMBER >= 0x03000000 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
@@ -224,6 +255,9 @@ static mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
mbedtls_pk_init(&self->pkey); mbedtls_pk_init(&self->pkey);
self->ciphersuites = NULL; self->ciphersuites = NULL;
self->handler = mp_const_none; self->handler = mp_const_none;
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
self->ecdsa_sign_callback = mp_const_none;
#endif
#ifdef MBEDTLS_DEBUG_C #ifdef MBEDTLS_DEBUG_C
// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
@@ -271,6 +305,10 @@ static void ssl_context_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
dest[0] = MP_OBJ_NEW_SMALL_INT(self->authmode); dest[0] = MP_OBJ_NEW_SMALL_INT(self->authmode);
} else if (attr == MP_QSTR_verify_callback) { } else if (attr == MP_QSTR_verify_callback) {
dest[0] = self->handler; dest[0] = self->handler;
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
} else if (attr == MP_QSTR_ecdsa_sign_callback) {
dest[0] = self->ecdsa_sign_callback;
#endif
} else { } else {
// Continue lookup in locals_dict. // Continue lookup in locals_dict.
dest[1] = MP_OBJ_SENTINEL; dest[1] = MP_OBJ_SENTINEL;
@@ -281,6 +319,11 @@ static void ssl_context_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
self->authmode = mp_obj_get_int(dest[1]); self->authmode = mp_obj_get_int(dest[1]);
dest[0] = MP_OBJ_NULL; dest[0] = MP_OBJ_NULL;
mbedtls_ssl_conf_authmode(&self->conf, self->authmode); mbedtls_ssl_conf_authmode(&self->conf, self->authmode);
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
} else if (attr == MP_QSTR_ecdsa_sign_callback) {
dest[0] = MP_OBJ_NULL;
self->ecdsa_sign_callback = dest[1];
#endif
} else if (attr == MP_QSTR_verify_callback) { } else if (attr == MP_QSTR_verify_callback) {
dest[0] = MP_OBJ_NULL; dest[0] = MP_OBJ_NULL;
self->handler = dest[1]; self->handler = dest[1];
@@ -307,7 +350,7 @@ static mp_obj_t ssl_context_get_ciphers(mp_obj_t self_in) {
mp_obj_t list = mp_obj_new_list(0, NULL); mp_obj_t list = mp_obj_new_list(0, NULL);
for (const int *cipher_list = mbedtls_ssl_list_ciphersuites(); *cipher_list; ++cipher_list) { for (const int *cipher_list = mbedtls_ssl_list_ciphersuites(); *cipher_list; ++cipher_list) {
const char *cipher_name = mbedtls_ssl_get_ciphersuite_name(*cipher_list); const char *cipher_name = mbedtls_ssl_get_ciphersuite_name(*cipher_list);
mp_obj_list_append(list, MP_OBJ_FROM_PTR(mp_obj_new_str(cipher_name, strlen(cipher_name)))); mp_obj_list_append(list, MP_OBJ_FROM_PTR(mp_obj_new_str_from_cstr(cipher_name)));
} }
return list; return list;
} }
@@ -346,22 +389,20 @@ static MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_set_ciphers_obj, ssl_context_set_ci
static void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) { static void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) {
size_t key_len; size_t key_len;
const byte *key = (const byte *)mp_obj_str_get_data(key_obj, &key_len); const unsigned char *key = asn1_get_data(key_obj, &key_len);
// len should include terminating null
int ret; int ret;
#if MBEDTLS_VERSION_NUMBER >= 0x03000000 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
ret = mbedtls_pk_parse_key(&self->pkey, key, key_len + 1, NULL, 0, mbedtls_ctr_drbg_random, &self->ctr_drbg); ret = mbedtls_pk_parse_key(&self->pkey, key, key_len, NULL, 0, mbedtls_ctr_drbg_random, &self->ctr_drbg);
#else #else
ret = mbedtls_pk_parse_key(&self->pkey, key, key_len + 1, NULL, 0); ret = mbedtls_pk_parse_key(&self->pkey, key, key_len, NULL, 0);
#endif #endif
if (ret != 0) { if (ret != 0) {
mbedtls_raise_error(MBEDTLS_ERR_PK_BAD_INPUT_DATA); // use general error for all key errors mbedtls_raise_error(MBEDTLS_ERR_PK_BAD_INPUT_DATA); // use general error for all key errors
} }
size_t cert_len; size_t cert_len;
const byte *cert = (const byte *)mp_obj_str_get_data(cert_obj, &cert_len); const unsigned char *cert = asn1_get_data(cert_obj, &cert_len);
// len should include terminating null ret = mbedtls_x509_crt_parse(&self->cert, cert, cert_len);
ret = mbedtls_x509_crt_parse(&self->cert, cert, cert_len + 1);
if (ret != 0) { if (ret != 0) {
mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors
} }
@@ -382,9 +423,8 @@ static MP_DEFINE_CONST_FUN_OBJ_3(ssl_context_load_cert_chain_obj, ssl_context_lo
static void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) { static void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) {
size_t cacert_len; size_t cacert_len;
const byte *cacert = (const byte *)mp_obj_str_get_data(cadata_obj, &cacert_len); const unsigned char *cacert = asn1_get_data(cadata_obj, &cacert_len);
// len should include terminating null int ret = mbedtls_x509_crt_parse(&self->cacert, cacert, cacert_len);
int ret = mbedtls_x509_crt_parse(&self->cacert, cacert, cacert_len + 1);
if (ret != 0) { if (ret != 0) {
mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors
} }
@@ -483,6 +523,9 @@ static int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock, 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) {
// Store the current SSL context.
store_active_context(ssl_context);
// Verify the socket object has the full stream protocol // Verify the socket object has the full stream protocol
mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
@@ -572,8 +615,8 @@ static mp_obj_t mod_ssl_cipher(mp_obj_t o_in) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
const char *cipher_suite = mbedtls_ssl_get_ciphersuite(&o->ssl); const char *cipher_suite = mbedtls_ssl_get_ciphersuite(&o->ssl);
const char *tls_version = mbedtls_ssl_get_version(&o->ssl); const char *tls_version = mbedtls_ssl_get_version(&o->ssl);
mp_obj_t tuple[2] = {mp_obj_new_str(cipher_suite, strlen(cipher_suite)), mp_obj_t tuple[2] = {mp_obj_new_str_from_cstr(cipher_suite),
mp_obj_new_str(tls_version, strlen(tls_version))}; mp_obj_new_str_from_cstr(tls_version)};
return mp_obj_new_tuple(2, tuple); return mp_obj_new_tuple(2, tuple);
} }
@@ -588,6 +631,9 @@ static mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
return MP_STREAM_ERROR; return MP_STREAM_ERROR;
} }
// Store the current SSL context.
store_active_context(o->ssl_context);
int ret = mbedtls_ssl_read(&o->ssl, buf, size); int ret = mbedtls_ssl_read(&o->ssl, buf, size);
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
// end of stream // end of stream
@@ -629,6 +675,9 @@ static mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
return MP_STREAM_ERROR; return MP_STREAM_ERROR;
} }
// Store the current SSL context.
store_active_context(o->ssl_context);
int ret = mbedtls_ssl_write(&o->ssl, buf, size); int ret = mbedtls_ssl_write(&o->ssl, buf, size);
if (ret >= 0) { if (ret >= 0) {
return ret; return ret;
@@ -666,6 +715,9 @@ static mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
mp_obj_t sock = self->sock; mp_obj_t sock = self->sock;
if (request == MP_STREAM_CLOSE) { if (request == MP_STREAM_CLOSE) {
// Clear the SSL context.
store_active_context(NULL);
if (sock == MP_OBJ_NULL) { if (sock == MP_OBJ_NULL) {
// Already closed socket, do nothing. // Already closed socket, do nothing.
return 0; return 0;
@@ -753,6 +805,57 @@ static MP_DEFINE_CONST_OBJ_TYPE(
/******************************************************************************/ /******************************************************************************/
// ssl module. // ssl module.
#if MICROPY_PY_SSL_ECDSA_SIGN_ALT
int micropy_mbedtls_ecdsa_sign_alt(const mbedtls_mpi *d, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen) {
uint8_t key[256];
// Check if the current context has an alternative sign function.
mp_obj_ssl_context_t *ssl_ctx = MP_STATE_THREAD(tls_ssl_context);
if (ssl_ctx == NULL || ssl_ctx->ecdsa_sign_callback == mp_const_none) {
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
}
size_t klen = mbedtls_mpi_size(d);
if (klen > sizeof(key)) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Convert the MPI private key (d) to a binary array
if (mbedtls_mpi_write_binary(d, key, klen) != 0) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
nlr_buf_t nlr;
mp_buffer_info_t sig_buf;
if (nlr_push(&nlr) == 0) {
mp_obj_t ret = mp_call_function_2(ssl_ctx->ecdsa_sign_callback,
mp_obj_new_bytearray_by_ref(klen, (void *)key),
mp_obj_new_bytearray_by_ref(hlen, (void *)hash));
if (ret == mp_const_none) {
// key couldn't be used by the alternative implementation.
nlr_pop();
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
}
mp_get_buffer_raise(ret, &sig_buf, MP_BUFFER_READ);
nlr_pop();
} else {
// The alternative implementation failed to sign.
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
// Check if the buffer fits.
if (sig_buf.len > sig_size) {
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
}
// Copy ASN.1 signature to buffer.
*slen = sig_buf.len;
memcpy(sig, sig_buf.buf, sig_buf.len);
return 0;
}
#endif
static const mp_rom_map_elem_t mp_module_tls_globals_table[] = { static const mp_rom_map_elem_t mp_module_tls_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tls) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tls) },

View File

@@ -143,6 +143,10 @@ static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
// Get size of aggregate type descriptor // Get size of aggregate type descriptor
static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) { static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) {
if (t->len == 0) {
syntax_error();
}
mp_uint_t total_size = 0; mp_uint_t total_size = 0;
mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]); mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
@@ -150,8 +154,15 @@ static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
switch (agg_type) { switch (agg_type) {
case STRUCT: case STRUCT:
if (t->len != 2) {
syntax_error();
}
return uctypes_struct_size(t->items[1], layout_type, max_field_size); return uctypes_struct_size(t->items[1], layout_type, max_field_size);
case PTR: case PTR:
// Second field ignored, but should still be present for consistency.
if (t->len != 2) {
syntax_error();
}
if (sizeof(void *) > *max_field_size) { if (sizeof(void *) > *max_field_size) {
*max_field_size = sizeof(void *); *max_field_size = sizeof(void *);
} }
@@ -167,15 +178,17 @@ static mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
if (item_s > *max_field_size) { if (item_s > *max_field_size) {
*max_field_size = item_s; *max_field_size = item_s;
} }
} else { } else if (t->len == 3) {
// Elements of array are aggregates // Elements of array are aggregates
item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size); item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size);
} else {
syntax_error();
} }
return item_s * arr_sz; return item_s * arr_sz;
} }
default: default:
assert(0); syntax_error();
} }
return total_size; return total_size;

View File

@@ -146,7 +146,7 @@ static void handle_op(mp_obj_webrepl_t *self) {
// Handle operations requiring opened file // Handle operations requiring opened file
mp_obj_t open_args[2] = { mp_obj_t open_args[2] = {
mp_obj_new_str(self->hdr.fname, strlen(self->hdr.fname)), mp_obj_new_str_from_cstr(self->hdr.fname),
MP_OBJ_NEW_QSTR(MP_QSTR_rb) MP_OBJ_NEW_QSTR(MP_QSTR_rb)
}; };

View File

@@ -60,6 +60,10 @@ typedef struct _network_cyw43_obj_t {
static const network_cyw43_obj_t network_cyw43_wl_sta = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_STA }; static const network_cyw43_obj_t network_cyw43_wl_sta = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_STA };
static const network_cyw43_obj_t network_cyw43_wl_ap = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_AP }; static const network_cyw43_obj_t network_cyw43_wl_ap = { { &mp_network_cyw43_type }, &cyw43_state, CYW43_ITF_AP };
// Avoid race conditions with callbacks by tracking the last up or down request
// we have made for each interface.
static bool if_active[2];
static void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { static void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
struct netif *netif = &self->cyw->netif[self->itf]; struct netif *netif = &self->cyw->netif[self->itf];
@@ -122,6 +126,10 @@ static MP_DEFINE_CONST_FUN_OBJ_3(network_cyw43_ioctl_obj, network_cyw43_ioctl);
/*******************************************************************************/ /*******************************************************************************/
// network API // network API
static uint32_t get_country_code(void) {
return CYW43_COUNTRY(mod_network_country_code[0], mod_network_country_code[1], 0);
}
static mp_obj_t network_cyw43_deinit(mp_obj_t self_in) { static mp_obj_t network_cyw43_deinit(mp_obj_t self_in) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
cyw43_deinit(self->cyw); cyw43_deinit(self->cyw);
@@ -132,10 +140,11 @@ static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_deinit_obj, network_cyw43_deinit)
static mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) { static mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) { if (n_args == 1) {
return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf)); return mp_obj_new_bool(if_active[self->itf]);
} else { } else {
uint32_t country = CYW43_COUNTRY(mod_network_country_code[0], mod_network_country_code[1], 0); bool value = mp_obj_is_true(args[1]);
cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1]), country); cyw43_wifi_set_up(self->cyw, self->itf, value, get_country_code());
if_active[self->itf] = value;
return mp_const_none; return mp_const_none;
} }
} }
@@ -311,7 +320,17 @@ static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_disconnect_obj, network_cyw43_dis
static mp_obj_t network_cyw43_isconnected(mp_obj_t self_in) { static mp_obj_t network_cyw43_isconnected(mp_obj_t self_in) {
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf) == 3); bool result = (cyw43_tcpip_link_status(self->cyw, self->itf) == CYW43_LINK_UP);
if (result && self->itf == CYW43_ITF_AP) {
// For AP we need to not only know if the link is up, but also if any stations
// have associated.
uint8_t mac_buf[6];
int num_stas = 1;
cyw43_wifi_ap_get_stas(self->cyw, &num_stas, mac_buf);
result = num_stas > 0;
}
return mp_obj_new_bool(result);
} }
static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_isconnected_obj, network_cyw43_isconnected); static MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_isconnected_obj, network_cyw43_isconnected);
@@ -351,13 +370,15 @@ static mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) {
if (self->itf != CYW43_ITF_AP) { if (self->itf != CYW43_ITF_AP) {
mp_raise_ValueError(MP_ERROR_TEXT("AP required")); mp_raise_ValueError(MP_ERROR_TEXT("AP required"));
} }
int num_stas; static const unsigned mac_len = 6;
uint8_t macs[32 * 6]; static const unsigned max_stas = 32;
int num_stas = max_stas;
uint8_t macs[max_stas * mac_len];
cyw43_wifi_ap_get_stas(self->cyw, &num_stas, macs); cyw43_wifi_ap_get_stas(self->cyw, &num_stas, macs);
mp_obj_t list = mp_obj_new_list(num_stas, NULL); mp_obj_t list = mp_obj_new_list(num_stas, NULL);
for (int i = 0; i < num_stas; ++i) { for (int i = 0; i < num_stas; ++i) {
mp_obj_t tuple[1] = { mp_obj_t tuple[1] = {
mp_obj_new_bytes(&macs[i * 6], 6), mp_obj_new_bytes(&macs[i * mac_len], mac_len),
}; };
((mp_obj_list_t *)MP_OBJ_TO_PTR(list))->items[i] = mp_obj_new_tuple(1, tuple); ((mp_obj_list_t *)MP_OBJ_TO_PTR(list))->items[i] = mp_obj_new_tuple(1, tuple);
} }
@@ -445,6 +466,10 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args")); mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
} }
// A number of these options only update buffers in memory, and
// won't do anything until the interface is cycled down and back up
bool cycle_active = false;
for (size_t i = 0; i < kwargs->alloc; ++i) { 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]; mp_map_elem_t *e = &kwargs->table[i];
@@ -457,6 +482,7 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
} }
case MP_QSTR_channel: { case MP_QSTR_channel: {
cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value)); cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value));
cycle_active = true;
break; break;
} }
case MP_QSTR_ssid: case MP_QSTR_ssid:
@@ -464,6 +490,7 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
size_t len; size_t len;
const char *str = mp_obj_str_get_data(e->value, &len); const char *str = mp_obj_str_get_data(e->value, &len);
cyw43_wifi_ap_set_ssid(self->cyw, len, (const uint8_t *)str); cyw43_wifi_ap_set_ssid(self->cyw, len, (const uint8_t *)str);
cycle_active = true;
break; break;
} }
case MP_QSTR_monitor: { case MP_QSTR_monitor: {
@@ -483,6 +510,7 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
} }
case MP_QSTR_security: { case MP_QSTR_security: {
cyw43_wifi_ap_set_auth(self->cyw, mp_obj_get_int(e->value)); cyw43_wifi_ap_set_auth(self->cyw, mp_obj_get_int(e->value));
cycle_active = true;
break; break;
} }
case MP_QSTR_key: case MP_QSTR_key:
@@ -490,6 +518,7 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
size_t len; size_t len;
const char *str = mp_obj_str_get_data(e->value, &len); const char *str = mp_obj_str_get_data(e->value, &len);
cyw43_wifi_ap_set_password(self->cyw, len, (const uint8_t *)str); cyw43_wifi_ap_set_password(self->cyw, len, (const uint8_t *)str);
cycle_active = true;
break; break;
} }
case MP_QSTR_pm: { case MP_QSTR_pm: {
@@ -519,6 +548,13 @@ static mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
} }
} }
// If the interface is already active, cycle it down and up
if (cycle_active && if_active[self->itf]) {
uint32_t country = get_country_code();
cyw43_wifi_set_up(self->cyw, self->itf, false, country);
cyw43_wifi_set_up(self->cyw, self->itf, true, country);
}
return mp_const_none; return mp_const_none;
} }
} }

View File

@@ -230,7 +230,7 @@ static mp_obj_t network_esp_hosted_config(size_t n_args, const mp_obj_t *args, m
case MP_QSTR_essid: { case MP_QSTR_essid: {
esp_hosted_netinfo_t netinfo; esp_hosted_netinfo_t netinfo;
esp_hosted_wifi_netinfo(&netinfo); esp_hosted_wifi_netinfo(&netinfo);
return mp_obj_new_str(netinfo.ssid, strlen(netinfo.ssid)); return mp_obj_new_str_from_cstr(netinfo.ssid);
} }
case MP_QSTR_security: { case MP_QSTR_security: {
esp_hosted_netinfo_t netinfo; esp_hosted_netinfo_t netinfo;

View File

@@ -113,7 +113,7 @@ mp_obj_t mod_network_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwa
case MP_QSTR_dns: { case MP_QSTR_dns: {
char addr_str[IPADDR_STRLEN_MAX]; char addr_str[IPADDR_STRLEN_MAX];
ipaddr_ntoa_r(dns_getserver(0), addr_str, sizeof(addr_str)); ipaddr_ntoa_r(dns_getserver(0), addr_str, sizeof(addr_str));
return mp_obj_new_str(addr_str, strlen(addr_str)); return mp_obj_new_str_from_cstr(addr_str);
} }
case MP_QSTR_prefer: { case MP_QSTR_prefer: {
return MP_OBJ_NEW_SMALL_INT(mp_mod_network_prefer_dns_use_ip_version); return MP_OBJ_NEW_SMALL_INT(mp_mod_network_prefer_dns_use_ip_version);
@@ -219,7 +219,7 @@ mp_obj_t mod_network_nic_ipconfig(struct netif *netif, size_t n_args, const mp_o
char addr_str[IPADDR_STRLEN_MAX]; char addr_str[IPADDR_STRLEN_MAX];
ipaddr_ntoa_r(netif_ip_addr6(netif, i), addr_str, sizeof(addr_str)); ipaddr_ntoa_r(netif_ip_addr6(netif, i), addr_str, sizeof(addr_str));
mp_obj_t tuple[4] = { mp_obj_t tuple[4] = {
mp_obj_new_str(addr_str, strlen(addr_str)), mp_obj_new_str_from_cstr(addr_str),
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_state(netif, i)), MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_state(netif, i)),
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_pref_life(netif, i)), // preferred MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_pref_life(netif, i)), // preferred
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_valid_life(netif, i)) MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_valid_life(netif, i))
@@ -297,20 +297,23 @@ mp_obj_t mod_network_nic_ipconfig(struct netif *netif, size_t n_args, const mp_o
char plain_ip[IPADDR_STRLEN_MAX]; char plain_ip[IPADDR_STRLEN_MAX];
char *split = strchr(input_str, '/'); char *split = strchr(input_str, '/');
const char *addr_str = input_str; const char *addr_str = input_str;
int to_copy = MIN(sizeof(plain_ip) - 1, addr_len);
memcpy(plain_ip, addr_str, to_copy);
if (split) { if (split) {
int to_copy = sizeof(plain_ip) - 1;
if (split - addr_str < to_copy) { if (split - addr_str < to_copy) {
to_copy = split - addr_str; to_copy = split - addr_str;
} }
memcpy(plain_ip, addr_str, to_copy);
mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL); mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL);
prefix_bits = mp_obj_get_int(prefix_obj); prefix_bits = mp_obj_get_int(prefix_obj);
if (mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr4) {
uint32_t mask = -(1u << (32 - prefix_bits));
ip_addr_set_ip4_u32_val(netmask, ((mask & 0xFF) << 24) | ((mask & 0xFF00) << 8) | ((mask >> 8) & 0xFF00) | ((mask >> 24) & 0xFF));
}
} else {
netmask = netif->netmask;
} }
if (mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr4) { plain_ip[to_copy] = '\0';
uint32_t mask = -(1u << (32 - prefix_bits)); if (!ipaddr_aton(plain_ip, &ip_addr)) {
ip_addr_set_ip4_u32_val(netmask, ((mask & 0xFF) << 24) | ((mask & 0xFF00) << 8) | ((mask >> 8) & 0xFF00) | ((mask >> 24) & 0xFF));
}
if (!ipaddr_aton(addr_str, &ip_addr)) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments")); mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
} }
if ((mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr6) != IP_IS_V6(&ip_addr) if ((mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr6) != IP_IS_V6(&ip_addr)

View File

@@ -41,6 +41,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/misc.h" #include "py/misc.h"
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/parsenum.h"
#include "shared/netutils/netutils.h" #include "shared/netutils/netutils.h"
#include "shared/runtime/softtimer.h" #include "shared/runtime/softtimer.h"
#include "extmod/modnetwork.h" #include "extmod/modnetwork.h"
@@ -75,6 +76,8 @@ typedef struct _nina_obj_t {
#define SO_NO_CHECK (0x100a) #define SO_NO_CHECK (0x100a)
#define NINAW10_POLL_INTERVAL (100) #define NINAW10_POLL_INTERVAL (100)
#define IPADDR_STRLEN_MAX 46
#define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS) #define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS)
#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__) #define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
@@ -87,6 +90,8 @@ static mp_sched_node_t mp_wifi_poll_node;
static soft_timer_entry_t mp_wifi_poll_timer; static soft_timer_entry_t mp_wifi_poll_timer;
static void network_ninaw10_deinit(void); static void network_ninaw10_deinit(void);
static bool network_ninaw10_dhcp_active = false;
static bool network_ninaw10_poll_list_is_empty(void) { static bool network_ninaw10_poll_list_is_empty(void) {
return MP_STATE_PORT(mp_wifi_poll_list) == NULL || return MP_STATE_PORT(mp_wifi_poll_list) == NULL ||
MP_STATE_PORT(mp_wifi_poll_list)->len == 0; MP_STATE_PORT(mp_wifi_poll_list)->len == 0;
@@ -199,6 +204,7 @@ static mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
mp_raise_msg_varg(&mp_type_OSError, mp_raise_msg_varg(&mp_type_OSError,
MP_ERROR_TEXT("failed to initialize Nina-W10 module, error: %d"), error); MP_ERROR_TEXT("failed to initialize Nina-W10 module, error: %d"), error);
} }
network_ninaw10_dhcp_active = true;
// check firmware version // check firmware version
uint8_t semver[NINA_FW_VER_LEN]; uint8_t semver[NINA_FW_VER_LEN];
if (nina_fw_version(semver) != 0) { if (nina_fw_version(semver) != 0) {
@@ -260,7 +266,7 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NINA_SEC_WPA_PSK} },
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
}; };
@@ -271,7 +277,6 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
// get ssid // get ssid
const char *ssid = mp_obj_str_get_str(args[ARG_ssid].u_obj); const char *ssid = mp_obj_str_get_str(args[ARG_ssid].u_obj);
if (strlen(ssid) == 0) { if (strlen(ssid) == 0) {
mp_raise_ValueError(MP_ERROR_TEXT("SSID can't be empty")); mp_raise_ValueError(MP_ERROR_TEXT("SSID can't be empty"));
} }
@@ -284,12 +289,6 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
// get security mode // get security mode
mp_uint_t security = args[ARG_security].u_int; mp_uint_t security = args[ARG_security].u_int;
if (security == -1 && self->itf == MOD_NETWORK_STA_IF) {
security = NINA_SEC_WPA_PSK;
} else if (security == -1 && self->itf == MOD_NETWORK_AP_IF) {
security = NINA_SEC_WEP;
}
// Ensure that the key is not empty if a security mode is used. // Ensure that the key is not empty if a security mode is used.
if (security != NINA_SEC_OPEN && strlen(key) == 0) { if (security != NINA_SEC_OPEN && strlen(key) == 0) {
mp_raise_ValueError(MP_ERROR_TEXT("key can't be empty")); mp_raise_ValueError(MP_ERROR_TEXT("key can't be empty"));
@@ -320,11 +319,6 @@ static mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL); soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
} else { } else {
mp_uint_t channel = args[ARG_channel].u_int; mp_uint_t channel = args[ARG_channel].u_int;
if (security != NINA_SEC_OPEN && security != NINA_SEC_WEP) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("AP mode only supports WEP or OPEN security modes"));
}
// Initialize WiFi in AP mode. // Initialize WiFi in AP mode.
if (nina_start_ap(ssid, security, key, channel) != 0) { if (nina_start_ap(ssid, security, key, channel) != 0) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to start in AP mode")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to start in AP mode"));
@@ -367,11 +361,155 @@ static mp_obj_t network_ninaw10_ifconfig(size_t n_args, const mp_obj_t *args) {
netutils_parse_ipv4_addr(items[2], ifconfig.gateway_addr, NETUTILS_BIG); netutils_parse_ipv4_addr(items[2], ifconfig.gateway_addr, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[3], ifconfig.dns_addr, NETUTILS_BIG); netutils_parse_ipv4_addr(items[3], ifconfig.dns_addr, NETUTILS_BIG);
nina_ifconfig(&ifconfig, true); nina_ifconfig(&ifconfig, true);
network_ninaw10_dhcp_active = false;
return mp_const_none; return mp_const_none;
} }
} }
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ninaw10_ifconfig_obj, 1, 2, network_ninaw10_ifconfig); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ninaw10_ifconfig_obj, 1, 2, network_ninaw10_ifconfig);
mp_obj_t network_ninaw10_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
nina_ifconfig_t ifconfig;
// get ifconfig info
nina_ifconfig(&ifconfig, false);
if (kwargs->used == 0) {
// Get config value
if (n_args != 1) {
mp_raise_TypeError(MP_ERROR_TEXT("must query one param"));
}
switch (mp_obj_str_get_qstr(args[0])) {
case MP_QSTR_dns: {
return netutils_format_ipv4_addr(ifconfig.dns_addr, NETUTILS_BIG);
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
} else {
// Set config value(s)
if (n_args != 0) {
mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
}
for (size_t i = 0; i < kwargs->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
mp_map_elem_t *e = &kwargs->table[i];
switch (mp_obj_str_get_qstr(e->key)) {
case MP_QSTR_dns: {
netutils_parse_ipv4_addr(e->value, ifconfig.dns_addr, NETUTILS_BIG);
nina_ifconfig(&ifconfig, true);
break;
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
}
}
}
return mp_const_none;
}
static mp_obj_t network_ninaw10_nic_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
nina_ifconfig_t ifconfig;
// get ifconfig info
nina_ifconfig(&ifconfig, false);
if (kwargs->used == 0) {
// Get config value
if (n_args != 2) {
mp_raise_TypeError(MP_ERROR_TEXT("must query one param"));
}
switch (mp_obj_str_get_qstr(args[1])) {
case MP_QSTR_dhcp4: {
return mp_obj_new_bool(network_ninaw10_dhcp_active);
}
case MP_QSTR_has_dhcp4: {
uint16_t ip_sum =
ifconfig.ip_addr[0] + ifconfig.ip_addr[1] + ifconfig.ip_addr[2] + ifconfig.ip_addr[3];
if (network_ninaw10_dhcp_active) {
return mp_obj_new_bool(ip_sum != 0);
} else {
return mp_const_false;
}
}
case MP_QSTR_addr4: {
mp_obj_t tuple[2] = {
netutils_format_ipv4_addr(ifconfig.ip_addr, NETUTILS_BIG),
netutils_format_ipv4_addr(ifconfig.subnet_addr, NETUTILS_BIG),
};
return mp_obj_new_tuple(2, tuple);
}
case MP_QSTR_gw4: {
return netutils_format_ipv4_addr(ifconfig.gateway_addr, NETUTILS_BIG);
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
return mp_const_none;
} else {
// Set config value(s)
if (n_args != 1) {
mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
}
for (size_t i = 0; i < kwargs->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
mp_map_elem_t *e = &kwargs->table[i];
switch (mp_obj_str_get_qstr(e->key)) {
case MP_QSTR_dhcp4: {
mp_raise_ValueError(MP_ERROR_TEXT("DHCP control unsupported"));
break;
}
case MP_QSTR_addr4: {
int prefix_bits = 32;
if (e->value != mp_const_none && mp_obj_is_str(e->value)) {
size_t addr_len;
const char *input_str = mp_obj_str_get_data(e->value, &addr_len);
char *split = strchr(input_str, '/');
if (split) {
mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL);
prefix_bits = mp_obj_get_int(prefix_obj);
uint32_t mask = -(1u << (32 - prefix_bits));
ifconfig.subnet_addr[0] = (mask >> 24) & 0xFF;
ifconfig.subnet_addr[1] = (mask >> 16) & 0xFF;
ifconfig.subnet_addr[2] = (mask >> 8) & 0xFF;
ifconfig.subnet_addr[3] = mask & 0xFF;
}
netutils_parse_ipv4_addr(e->value, ifconfig.ip_addr, NETUTILS_BIG);
} else if (e->value != mp_const_none) {
mp_obj_t *items;
mp_obj_get_array_fixed_n(e->value, 2, &items);
netutils_parse_ipv4_addr(items[0], ifconfig.ip_addr, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[1], ifconfig.subnet_addr, NETUTILS_BIG);
}
nina_ifconfig(&ifconfig, true);
network_ninaw10_dhcp_active = false;
break;
}
case MP_QSTR_gw4: {
netutils_parse_ipv4_addr(e->value, ifconfig.gateway_addr, NETUTILS_BIG);
nina_ifconfig(&ifconfig, true);
network_ninaw10_dhcp_active = false;
break;
}
default: {
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
break;
}
}
}
}
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ninaw10_nic_ipconfig_obj, 1, network_ninaw10_nic_ipconfig);
static mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { static mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
nina_obj_t *self = MP_OBJ_TO_PTR(args[0]); nina_obj_t *self = MP_OBJ_TO_PTR(args[0]);
(void)self; (void)self;
@@ -386,7 +524,7 @@ static mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_m
case MP_QSTR_ssid: { case MP_QSTR_ssid: {
nina_netinfo_t netinfo; nina_netinfo_t netinfo;
nina_netinfo(&netinfo); nina_netinfo(&netinfo);
return mp_obj_new_str(netinfo.ssid, strlen(netinfo.ssid)); return mp_obj_new_str_from_cstr(netinfo.ssid);
} }
case MP_QSTR_security: { case MP_QSTR_security: {
nina_netinfo_t netinfo; nina_netinfo_t netinfo;
@@ -856,6 +994,7 @@ static const mp_rom_map_elem_t nina_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_ninaw10_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_ninaw10_disconnect_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_ninaw10_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_ninaw10_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_ninaw10_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_ninaw10_ifconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&network_ninaw10_nic_ipconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_ninaw10_config_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_ninaw10_config_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_ninaw10_status_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_ninaw10_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_ninaw10_ioctl_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_ninaw10_ioctl_obj) },

326
extmod/network_ppp_lwip.c Normal file
View File

@@ -0,0 +1,326 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2024 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/stream.h"
#include "extmod/modnetwork.h"
#if MICROPY_PY_NETWORK_PPP_LWIP
#include "lwip/dns.h"
#include "netif/ppp/ppp.h"
#include "netif/ppp/pppapi.h"
#include "netif/ppp/pppos.h"
// Enable this to see the serial data going between the PPP layer.
#define PPP_TRACE_IN_OUT (0)
typedef enum {
STATE_INACTIVE,
STATE_ACTIVE,
STATE_ERROR,
STATE_CONNECTING,
STATE_CONNECTED,
} network_ppp_state_t;
typedef struct _network_ppp_obj_t {
mp_obj_base_t base;
network_ppp_state_t state;
int error_code;
mp_obj_t stream;
ppp_pcb *pcb;
struct netif netif;
} network_ppp_obj_t;
const mp_obj_type_t mp_network_ppp_lwip_type;
static mp_obj_t network_ppp___del__(mp_obj_t self_in);
static void network_ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
network_ppp_obj_t *self = ctx;
switch (err_code) {
case PPPERR_NONE:
self->state = STATE_CONNECTED;
break;
case PPPERR_USER:
if (self->state >= STATE_ERROR) {
// Disable UART IRQ.
mp_obj_t dest[3];
mp_load_method(self->stream, MP_QSTR_irq, dest);
dest[2] = mp_const_none;
mp_call_method_n_kw(1, 0, dest);
// Indicate that the IRQ is disabled.
self->state = STATE_ACTIVE;
}
// Clean up the PPP PCB.
network_ppp___del__(MP_OBJ_FROM_PTR(self));
break;
default:
self->state = STATE_ERROR;
self->error_code = err_code;
break;
}
}
static mp_obj_t network_ppp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_obj_t stream = all_args[0];
mp_get_stream_raise(stream, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE);
network_ppp_obj_t *self = mp_obj_malloc_with_finaliser(network_ppp_obj_t, type);
self->state = STATE_INACTIVE;
self->stream = stream;
self->pcb = NULL;
return MP_OBJ_FROM_PTR(self);
}
static mp_obj_t network_ppp___del__(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state >= STATE_ACTIVE) {
if (self->state >= STATE_ERROR) {
// Still connected over the UART stream.
// Force the connection to close, with nocarrier=1.
self->state = STATE_INACTIVE;
ppp_close(self->pcb, 1);
}
// Free PPP PCB and reset state.
self->state = STATE_INACTIVE;
ppp_free(self->pcb);
self->pcb = NULL;
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp___del___obj, network_ppp___del__);
static mp_obj_t network_ppp_poll(size_t n_args, const mp_obj_t *args) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (self->state <= STATE_ERROR) {
return MP_OBJ_NEW_SMALL_INT(-MP_EPERM);
}
mp_int_t total_len = 0;
for (;;) {
uint8_t buf[256];
int err;
mp_uint_t len = mp_stream_rw(self->stream, buf, sizeof(buf), &err, 0);
if (len == 0) {
break;
}
#if PPP_TRACE_IN_OUT
mp_printf(&mp_plat_print, "ppp_in(n=%u,data=", len);
for (size_t i = 0; i < len; ++i) {
mp_printf(&mp_plat_print, "%02x:", buf[i]);
}
mp_printf(&mp_plat_print, ")\n");
#endif
pppos_input(self->pcb, (u8_t *)buf, len);
total_len += len;
}
return MP_OBJ_NEW_SMALL_INT(total_len);
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ppp_poll_obj, 1, 2, network_ppp_poll);
static mp_obj_t network_ppp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
if (n_args != 1 && kwargs->used != 0) {
mp_raise_TypeError(MP_ERROR_TEXT("either pos or kw args are allowed"));
}
// network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (kwargs->used != 0) {
for (size_t i = 0; i < kwargs->alloc; i++) {
if (mp_map_slot_is_filled(kwargs, i)) {
switch (mp_obj_str_get_qstr(kwargs->table[i].key)) {
default:
break;
}
}
}
return mp_const_none;
}
if (n_args != 2) {
mp_raise_TypeError(MP_ERROR_TEXT("can query only one param"));
}
mp_obj_t val = mp_const_none;
switch (mp_obj_str_get_qstr(args[1])) {
default:
mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
}
return val;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ppp_config_obj, 1, network_ppp_config);
static mp_obj_t network_ppp_status(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state == STATE_ERROR) {
return MP_OBJ_NEW_SMALL_INT(-self->error_code);
} else {
return MP_OBJ_NEW_SMALL_INT(self->state);
}
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp_status_obj, network_ppp_status);
static u32_t network_ppp_output_callback(ppp_pcb *pcb, const void *data, u32_t len, void *ctx) {
network_ppp_obj_t *self = ctx;
#if PPP_TRACE_IN_OUT
mp_printf(&mp_plat_print, "ppp_out(n=%u,data=", len);
for (size_t i = 0; i < len; ++i) {
mp_printf(&mp_plat_print, "%02x:", ((const uint8_t *)data)[i]);
}
mp_printf(&mp_plat_print, ")\n");
#endif
int err;
// The return value from this output callback is the number of bytes written out.
// If it's less than the requested number of bytes then lwIP will propagate out an error.
return mp_stream_rw(self->stream, (void *)data, len, &err, MP_STREAM_RW_WRITE);
}
static mp_obj_t network_ppp_connect(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
enum { ARG_security, ARG_user, ARG_key };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PPPAUTHTYPE_NONE} },
{ MP_QSTR_user, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
};
mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args);
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (self->state == STATE_INACTIVE) {
self->pcb = pppos_create(&self->netif, network_ppp_output_callback, network_ppp_status_cb, self);
if (self->pcb == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("pppos_create failed"));
}
self->state = STATE_ACTIVE;
// Enable UART IRQ to call PPP.poll() when incoming data is ready.
mp_obj_t dest[4];
mp_load_method(self->stream, MP_QSTR_irq, dest);
dest[2] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_ppp_poll_obj), MP_OBJ_FROM_PTR(self));
dest[3] = mp_load_attr(self->stream, MP_QSTR_IRQ_RXIDLE);
mp_call_method_n_kw(2, 0, dest);
}
if (self->state == STATE_CONNECTING || self->state == STATE_CONNECTED) {
mp_raise_OSError(MP_EALREADY);
}
switch (parsed_args[ARG_security].u_int) {
case PPPAUTHTYPE_NONE:
case PPPAUTHTYPE_PAP:
case PPPAUTHTYPE_CHAP:
break;
default:
mp_raise_ValueError(MP_ERROR_TEXT("invalid auth"));
}
if (parsed_args[ARG_security].u_int != PPPAUTHTYPE_NONE) {
const char *user_str = mp_obj_str_get_str(parsed_args[ARG_user].u_obj);
const char *key_str = mp_obj_str_get_str(parsed_args[ARG_key].u_obj);
ppp_set_auth(self->pcb, parsed_args[ARG_security].u_int, user_str, key_str);
}
netif_set_default(self->pcb->netif);
ppp_set_usepeerdns(self->pcb, true);
if (ppp_connect(self->pcb, 0) != ERR_OK) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("ppp_connect failed"));
}
self->state = STATE_CONNECTING;
// Do a poll in case there is data waiting on the input stream.
network_ppp_poll(1, args);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ppp_connect_obj, 1, network_ppp_connect);
static mp_obj_t network_ppp_disconnect(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state == STATE_CONNECTING || self->state == STATE_CONNECTED) {
// Initiate close and wait for PPPERR_USER callback.
ppp_close(self->pcb, 0);
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp_disconnect_obj, network_ppp_disconnect);
static mp_obj_t network_ppp_isconnected(mp_obj_t self_in) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(self->state == STATE_CONNECTED);
}
static MP_DEFINE_CONST_FUN_OBJ_1(network_ppp_isconnected_obj, network_ppp_isconnected);
static mp_obj_t network_ppp_ifconfig(size_t n_args, const mp_obj_t *args) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
return mod_network_nic_ifconfig(&self->netif, n_args - 1, args + 1);
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ppp_ifconfig_obj, 1, 2, network_ppp_ifconfig);
static mp_obj_t network_ppp_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
network_ppp_obj_t *self = MP_OBJ_TO_PTR(args[0]);
return mod_network_nic_ipconfig(&self->netif, n_args - 1, args + 1, kwargs);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(network_ppp_ipconfig_obj, 1, network_ppp_ipconfig);
static const mp_rom_map_elem_t network_ppp_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&network_ppp___del___obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_ppp_config_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_ppp_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_ppp_connect_obj) },
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_ppp_disconnect_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_ppp_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_ppp_ifconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&network_ppp_ipconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&network_ppp_poll_obj) },
{ MP_ROM_QSTR(MP_QSTR_SEC_NONE), MP_ROM_INT(PPPAUTHTYPE_NONE) },
{ MP_ROM_QSTR(MP_QSTR_SEC_PAP), MP_ROM_INT(PPPAUTHTYPE_PAP) },
{ MP_ROM_QSTR(MP_QSTR_SEC_CHAP), MP_ROM_INT(PPPAUTHTYPE_CHAP) },
};
static MP_DEFINE_CONST_DICT(network_ppp_locals_dict, network_ppp_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
mp_network_ppp_lwip_type,
MP_QSTR_PPP,
MP_TYPE_FLAG_NONE,
make_new, network_ppp_make_new,
locals_dict, &network_ppp_locals_dict
);
#endif

View File

@@ -58,9 +58,11 @@
#include "shared/netutils/netutils.h" #include "shared/netutils/netutils.h"
#include "lib/wiznet5k/Ethernet/wizchip_conf.h" #include "lib/wiznet5k/Ethernet/wizchip_conf.h"
#include "lib/wiznet5k/Ethernet/socket.h" #include "lib/wiznet5k/Ethernet/socket.h"
#include "lwip/apps/mdns.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/dns.h" #include "lwip/dns.h"
#include "lwip/dhcp.h" #include "lwip/dhcp.h"
#include "lwip/ethip6.h"
#include "netif/etharp.h" #include "netif/etharp.h"
#define TRACE_ETH_TX (0x0002) #define TRACE_ETH_TX (0x0002)
@@ -200,6 +202,9 @@ static void wiznet5k_config_interrupt(bool enabled) {
void wiznet5k_deinit(void) { void wiznet5k_deinit(void) {
for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
if (netif == &wiznet5k_obj.netif) { if (netif == &wiznet5k_obj.netif) {
#if LWIP_MDNS_RESPONDER
mdns_resp_remove_netif(&wiznet5k_obj.netif);
#endif
netif_remove(netif); netif_remove(netif);
netif->flags = 0; netif->flags = 0;
break; break;
@@ -297,13 +302,21 @@ static err_t wiznet5k_netif_init(struct netif *netif) {
netif->hwaddr_len = sizeof(netif->hwaddr); netif->hwaddr_len = sizeof(netif->hwaddr);
int ret = WIZCHIP_EXPORT(socket)(0, Sn_MR_MACRAW, 0, 0); int ret = WIZCHIP_EXPORT(socket)(0, Sn_MR_MACRAW, 0, 0);
if (ret != 0) { if (ret != 0) {
printf("WIZNET fatal error in netifinit: %d\n", ret); printf("WIZNET fatal error in netif_init: %d\n", ret);
return ERR_IF; return ERR_IF;
} }
// Enable MAC filtering so we only get frames destined for us, to reduce load on lwIP // Enable MAC filtering so we only get frames destined for us, to reduce load on lwIP
setSn_MR(0, getSn_MR(0) | Sn_MR_MFEN); setSn_MR(0, getSn_MR(0) | Sn_MR_MFEN);
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
netif->flags |= NETIF_FLAG_MLD6;
#else
// Drop IPv6 packets if firmware does not support it
setSn_MR(0, getSn_MR(0) | Sn_MR_MIP6B);
#endif
return ERR_OK; return ERR_OK;
} }
@@ -325,6 +338,12 @@ static void wiznet5k_lwip_init(wiznet5k_obj_t *self) {
self->netif.flags |= NETIF_FLAG_UP; self->netif.flags |= NETIF_FLAG_UP;
dhcp_start(&self->netif); dhcp_start(&self->netif);
self->netif.flags &= ~NETIF_FLAG_UP; self->netif.flags &= ~NETIF_FLAG_UP;
#if LWIP_MDNS_RESPONDER
// NOTE: interface is removed in ::wiznet5k_deinit(), which is called as
// part of the init sequence.
mdns_resp_add_netif(&self->netif, mod_network_hostname_data);
#endif
} }
void wiznet5k_poll(void) { void wiznet5k_poll(void) {
@@ -847,6 +866,10 @@ static mp_obj_t wiznet5k_active(size_t n_args, const mp_obj_t *args) {
setSHAR(mac); setSHAR(mac);
} }
#if WIZNET5K_WITH_LWIP_STACK && LWIP_IPV6
netif_create_ip6_linklocal_address(&self->netif, 1);
#endif
// seems we need a small delay after init // seems we need a small delay after init
mp_hal_delay_ms(250); mp_hal_delay_ms(250);

View File

@@ -139,7 +139,7 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) {
} }
// delegate to vfs.stat() method // delegate to vfs.stat() method
mp_obj_t path_o = mp_obj_new_str(path_out, strlen(path_out)); mp_obj_t path_o = mp_obj_new_str_from_cstr(path_out);
mp_obj_t stat; mp_obj_t stat;
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
@@ -273,7 +273,7 @@ mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) {
mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len); mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len);
} }
for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) {
if ((mnt_str != NULL && !memcmp(mnt_str, (*vfsp)->str, mnt_len + 1)) || (*vfsp)->obj == mnt_in) { if ((mnt_str != NULL && mnt_len == (*vfsp)->len && !memcmp(mnt_str, (*vfsp)->str, mnt_len)) || (*vfsp)->obj == mnt_in) {
vfs = *vfsp; vfs = *vfsp;
*vfsp = (*vfsp)->next; *vfsp = (*vfsp)->next;
break; break;

View File

@@ -46,31 +46,45 @@ void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
} }
} }
// Helper function to minimise code size of read/write functions
// note the n_args argument is moved to the end for further code size reduction (args keep same position in caller and callee).
static int mp_vfs_blockdev_call_rw(mp_obj_t *args, size_t block_num, size_t block_off, size_t len, void *buf, size_t n_args) {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf};
args[2] = MP_OBJ_NEW_SMALL_INT(block_num);
args[3] = MP_OBJ_FROM_PTR(&ar);
args[4] = MP_OBJ_NEW_SMALL_INT(block_off); // ignored for n_args == 2
mp_obj_t ret = mp_call_method_n_kw(n_args, 0, args);
if (ret == mp_const_none) {
return 0;
} else {
// Some block devices return a bool indicating success, so
// convert those to an errno integer code.
if (ret == mp_const_true) {
return 0;
} else if (ret == mp_const_false) {
return -MP_EIO;
}
// Block device functions are expected to return 0 on success
// and negative integer on errors. Check for positive integer
// results as some callers (i.e. littlefs) will produce corrupt
// results from these.
int i = MP_OBJ_SMALL_INT_VALUE(ret);
return i > 0 ? (-MP_EINVAL) : i;
}
}
int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) { int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) {
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
mp_uint_t (*f)(uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2]; mp_uint_t (*f)(uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
return f(buf, block_num, num_blocks); return f(buf, block_num, num_blocks);
} else { } else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, buf}; return mp_vfs_blockdev_call_rw(self->readblocks, block_num, 0, num_blocks * self->block_size, buf, 2);
self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
self->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
mp_call_method_n_kw(2, 0, self->readblocks);
// TODO handle error return
return 0;
} }
} }
int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) { int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf}; return mp_vfs_blockdev_call_rw(self->readblocks, block_num, block_off, len, buf, 3);
self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
self->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
self->readblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off);
mp_obj_t ret = mp_call_method_n_kw(3, 0, self->readblocks);
if (ret == mp_const_none) {
return 0;
} else {
return MP_OBJ_SMALL_INT_VALUE(ret);
}
} }
int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) { int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) {
@@ -83,12 +97,7 @@ int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_
mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2]; mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
return f(buf, block_num, num_blocks); return f(buf, block_num, num_blocks);
} else { } else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, (void *)buf}; return mp_vfs_blockdev_call_rw(self->writeblocks, block_num, 0, num_blocks * self->block_size, (void *)buf, 2);
self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
mp_call_method_n_kw(2, 0, self->writeblocks);
// TODO handle error return
return 0;
} }
} }
@@ -97,17 +106,7 @@ int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t
// read-only block device // read-only block device
return -MP_EROFS; return -MP_EROFS;
} }
return mp_vfs_blockdev_call_rw(self->writeblocks, block_num, block_off, len, (void *)buf, 3);
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, (void *)buf};
self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
self->writeblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off);
mp_obj_t ret = mp_call_method_n_kw(3, 0, self->writeblocks);
if (ret == mp_const_none) {
return 0;
} else {
return MP_OBJ_SMALL_INT_VALUE(ret);
}
} }
mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) { mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) {

View File

@@ -114,6 +114,11 @@ static mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
mp_raise_OSError(fresult_to_errno_table[res]); mp_raise_OSError(fresult_to_errno_table[res]);
} }
// set the filesystem label if it's configured
#ifdef MICROPY_HW_FLASH_FS_LABEL
f_setlabel(&vfs->fatfs, MICROPY_HW_FLASH_FS_LABEL);
#endif
return mp_const_none; return mp_const_none;
} }
static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs); static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs);
@@ -144,7 +149,7 @@ static mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
// make 4-tuple with info about this entry // make 4-tuple with info about this entry
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL));
if (self->is_str) { if (self->is_str) {
t->items[0] = mp_obj_new_str(fn, strlen(fn)); t->items[0] = mp_obj_new_str_from_cstr(fn);
} else { } else {
t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn)); t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn));
} }
@@ -291,7 +296,7 @@ static mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
if (res != FR_OK) { if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]); mp_raise_OSError(fresult_to_errno_table[res]);
} }
return mp_obj_new_str(buf, strlen(buf)); return mp_obj_new_str_from_cstr(buf);
} }
static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd); static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);

View File

@@ -192,7 +192,7 @@ static mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) {
// make 4-tuple with info about this entry // make 4-tuple with info about this entry
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL));
if (self->is_str) { if (self->is_str) {
t->items[0] = mp_obj_new_str(info.name, strlen(info.name)); t->items[0] = mp_obj_new_str_from_cstr(info.name);
} else { } else {
t->items[0] = mp_obj_new_bytes((const byte *)info.name, strlen(info.name)); t->items[0] = mp_obj_new_bytes((const byte *)info.name, strlen(info.name));
} }

View File

@@ -194,7 +194,7 @@ static mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) {
} }
#endif #endif
} }
return mp_obj_new_str(ret, strlen(ret)); return mp_obj_new_str_from_cstr(ret);
} }
static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd);
@@ -234,7 +234,7 @@ static mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
if (self->is_str) { if (self->is_str) {
t->items[0] = mp_obj_new_str(fn, strlen(fn)); t->items[0] = mp_obj_new_str_from_cstr(fn);
} else { } else {
t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn)); t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn));
} }

View File

@@ -160,12 +160,27 @@ static mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
#if defined(__APPLE__) #if defined(__APPLE__)
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP) #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
// In debug builds fsync (i.e. _commit on windows) will generate a debug report via _ASSERTE when
// called with non-redirected stdin/stdout/stderr (i.e. _isatty) handles because FlushFileBuffers,
// which it calls internally, will fail since console output is not buffered.
// In release builds it also fails, but merely returns an error which is handled appropriately below.
// The check for the handle being stdin/stdout/stderr is added explicitly because according to
// the documentation _isatty is also true for serial ports for instance.
#ifdef _DEBUG
if ((o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO) && _isatty(o->fd)) {
return 0;
}
#endif
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == EBADF) #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == EBADF)
#else #else
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL) #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL)
#endif #endif
MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), { MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), {
if (VFS_POSIX_STREAM_STDIO_ERR_CATCH if (VFS_POSIX_STREAM_STDIO_ERR_CATCH
// Note: comparing fd against the standard FILENOs is technically not correct, for example:
// sys.stderr.close() in Python code results in close(STDERR_FILENO) here, but because
// open() uses the next available file descriptor, opening an arbitrary file with
// fd = open('/some/file') means that fd becomes STDERR_FILENO.
&& (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) { && (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) {
return 0; return 0;
} }

View File

@@ -19,7 +19,10 @@
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
#define FLT_EVAL_METHOD 0 // These lines verify that FLT_EVAL_METHOD==0, MicroPython's libm requires this.
// If compilation fails here then check the host compiler's FLT_EVAL_METHOD.
typedef float float_t;
typedef double double_t;
#define FORCE_EVAL(x) do { \ #define FORCE_EVAL(x) do { \
if (sizeof(x) == sizeof(float)) { \ if (sizeof(x) == sizeof(float)) { \

View File

@@ -24,7 +24,9 @@
*/ */
#include "fdlibm.h" #include "fdlibm.h"
#ifndef _IEEE_LIBM
#define _IEEE_LIBM 1 #define _IEEE_LIBM 1
#endif
#ifdef __STDC__ #ifdef __STDC__
float lgammaf(float x) float lgammaf(float x)

View File

@@ -24,7 +24,9 @@
#include "math.h" #include "math.h"
#include "fdlibm.h" #include "fdlibm.h"
#ifndef _IEEE_LIBM
#define _IEEE_LIBM 1 #define _IEEE_LIBM 1
#endif
#ifdef __STDC__ #ifdef __STDC__
float tgammaf(float x) float tgammaf(float x)

View File

@@ -15,7 +15,10 @@
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
#define FLT_EVAL_METHOD 0 // These lines verify that FLT_EVAL_METHOD==0, MicroPython's libm requires this.
// If compilation fails here then check the host compiler's FLT_EVAL_METHOD.
typedef float float_t;
typedef double double_t;
#define FORCE_EVAL(x) do { \ #define FORCE_EVAL(x) do { \
if (sizeof(x) == sizeof(float)) { \ if (sizeof(x) == sizeof(float)) { \

View File

@@ -1,18 +0,0 @@
Tinytest is a tiny little test framework written in C by Nick Mathewson.
It is distributed under the 3-clause BSD license. You can use it in
your own programs so long as you follow the license's conditions.
It's been tested on Windows, Mac, and many of the free Unixes.
It knows how to fork before running certain tests, and it makes
text-mode output in a format I like.
For info on how to use it, check out tinytest_demo.c.
You can get the latest version using Git, by pulling from
git://github.com/nmathewson/tinytest.git
Patches are welcome. Patches that turn this from tinytest to hugetest
will not be applied. If you want a huge test framework, use CUnit.

Some files were not shown because too many files have changed in this diff Show More