wokwi/rp2040js

Support for newer CircuitPython firmwares

rgov opened this issue · 4 comments

rgov commented

rp2040js is unable to boot newer CircuitPython firmware. The default version is 8.0.2, which indeed works. Since then, several releases have been made. I tested a few of them:

Version Works?
8.0.5
8.1.0 hangs
8.2.0 [RP2040] read from address 100a692d, which is not 32 bit aligned

Others including 8.2.9 and 9.0.0-beta.0 fail with similar unaligned read errors:

$  npm run start:circuitpython -- --image=adafruit-circuitpython-raspberry_pi_pico-en_US-9.0.0-beta.0.uf2
...
Error: [RP2040] read from address 2, which is not 32 bit aligned
    at ConsoleLogger.error (/private/tmp/rp2040js/src/utils/logging.ts:48:15)
    at RP2040.readUint32 (/private/tmp/rp2040js/src/rp2040.ts:202:19)
    at CortexM0Core.readUint32 (/private/tmp/rp2040js/src/cortex-m0-core.ts:194:24)
    at CortexM0Core.executeInstruction (/private/tmp/rp2040js/src/cortex-m0-core.ts:826:36)
    at RP2040.execute (/private/tmp/rp2040js/src/rp2040.ts:381:17)
    at Timeout._onTimeout (/private/tmp/rp2040js/src/rp2040.ts:384:49)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7)
rgov commented

Performed a bisection of commits between 8.0.5 and 8.1.0 and found this was the first that fails: adafruit/circuitpython@cbfb2d0 (which modifies ports/raspberrypi/supervisor/port.c).

After reverting that commit, rp2040js can run all the way up to 9.0.0!

$ git apply -R <(git diff cbfb2d0'^':ports/raspberrypi/supervisor/port.c cbfb2d0:ports/raspberrypi/supervisor/port.c)
Details of the awful bisect script

I had to remove the part of demo/micropython-run.ts that handles process.stdin. Note I'm on macOS so gmake is GNU make, sed is slightly different.

#!/bin/bash -eu

make fetch-submodules

make -C mpy-cross

cd ports/raspberrypi
sed -i '' 's/-Werror //g' Makefile 
gmake -j8 BOARD=raspberry_pi_pico

git checkout Makefile

# Run the program with a timeout
cd /tmp/rp2040js
exec gtimeout 12 npm run start:circuitpython -- --image=circuitpython/ports/raspberrypi/build-raspberry_pi_pico/firmware.uf2 --expect-text "Press any key to enter the REPL"

Good job! I believe this is the culprit:

adafruit/circuitpython@cbfb2d0#diff-a05d314adb461e8edad8e3a970d717cafb82f7a41fa4e9fe4220e003f7c947abR107-R111

    // Load from the XIP memory space that doesn't cache. That way we don't
    // evict anything else. The code we're loading is linked to the RAM address
    // anyway.
    size_t nocache = 0x03000000;
rgov commented

That would be the offset from XIP_BASE to XIP_NOCACHE_NOALLOC_BASE. The RP2040 datasheet, §2.6.3.1 "XIP Cache" explains this is a "mirror" of the base address which bypasses the cache.

Thanks again for spotting the issue. One of the best bug reports I ever received :)