rp2: Flash writes disrupt UART IRQ
Port, board and/or hardware
rp2
MicroPython version
All.
Reproduction
Attempting to stream data from a UART to Flash - ie: servicing a soft (MicroPython) UART IRQ and writing the UART contents to a file on Flash - will result in lost data.
Using the same code and writing the same data to an SD card works fine.
Expected behaviour
No data should be lost.
Observed behaviour
Flash writes on RP2 disable all interrupts to avoid any code running from Flash while it's being written.
Since the UART copy from its 32 byte buffer into the user-specified (size) ring buffer requires the IRQ to fire, then writing to flash will lose arbitrary portions of incoming UART data since they will never make it to the ring buffer.
Additional Information
It's possible, maybe, that this could be fixed by moving the UART IRQ handler to RAM and being very careful about what it does. IE: This could not interop with a "hard" IRQ since we can't predict what the user might be doing (even if they don't allocate RAM).
AIUI the normal soft UART IRQ is dispatched and handled by MicroPython outside of the IRQ handler so this might just work.
Code of Conduct
Yes, I agree
rp2: flash writes broken after starting core1 and performing a soft reset
Port, board and/or hardware
rp2040, rp2350 (Pico, Pico 2, Pico W, Pico 2 W)
MicroPython version
N/A, but tested on MicroPython v1.25.0-preview.217.gb4f53a0e51.dirty and various stable releases.
Reproduction
If I run the following code (via Thonny) then it breaks my ability to save files (trying to write to flash will cause a lockup) until I hard reset:
import _thread
def core1():
pass
_thread.start_new_thread(core1, ())
while True:
pass
If I remove multicore_lockout_start_blocking(); and multicore_lockout_end_blocking(); it will work fine. Since my core1 is already doing nothing (spinning on WFI) there's no need to make sure it's doing nothing.
Expected behaviour
I expect it to soft reset and for flash IO to work as normal.
Observed behaviour
A "Ctrl+C" will stop the main loop on core0 but leave core1 spinning, flash writes will work.
A soft reset (stop in Thonny) will stop/reset core1, and flash writes will break.
Additional Information
The bug happens because a soft reset will reset core1, but will not reset the multicore lockout victim state. The check on multicore_lockout_victim_is_initialized(1 - get_core_num()) will pass, but multicore_lockout_start_blocking() will block forever, since multicore_lockout_victim_is_initialized just returns an incorrect boolean value that isn't reset by multicore_reset_core1()
This is documented in Pico SDK here: https://github.com/raspberrypi/pico-sdk/blob/95ea6acad131124694cda1c162c52cd30e0aece0/src/rp2_common/pico_multicore/multicore.c#L26-L32
This is an upstream bug in Pico SDK, documented here https://github.com/raspberrypi/pico-sdk/issues/2201
There may be a downstream workaround in the interim. For example MICROPY_BEGIN_ATOMIC_SECTION checks for core1_entry
Code of Conduct
Yes, I agree