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