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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>