Open Gadgetoid opened 2 years ago
relates to #748
@Gadgetoid There's no reason that MicroPython's gc heap needs to be zero initialised at boot (in fact, the gc doesn't assume that it has been initialised, because on other platforms it comes from malloc).
It should be pretty straightforward to put it in a different section (e.g. .noinit
), or better do what we do on stm32 where it's just defined entirely in the linker config as a start and end symbol used directly by gc_init().
@jimmo the zero fill only accounted for something like 20ms of the startup delay, with the remaining ~120 being the initialised SRAM copy. Definitely worth the gains, but not the full picture.
I didn’t try to figure out what portion of the SRAM copy was our C++ modules versus MicroPython itself but we’re extremely cautious with RAM usage so I’d hope not much!
I need to improve my objdump/nm skills so I can figure out where the main thrust of the delay is coming from since - as you imply - fixing it downstream is also an option!
8ms from cold boot to pin toggle low level is hard to pass up though- even if we can get full MicroPython started in 50ms now.
Edit: Note I tested the affect noinit might have on gc_heap
by building a version with a smaller gc_heap
(around 16K IIRC) and that's how I measured the 20ms speedup. .noinit
might gain slightly over 20ms.
In fact we have a patch in our build (excuse the patch of a patch here) to set the ROSC early and this dramatically speeds up the BSS/Zero init steps- https://github.com/pimoroni/pimoroni-pico/pull/480/commits/69493e5af76d6196beac30ad2592f6605244486c
ldr r0, =(ROSC_BASE + ROSC_DIV_OFFSET)
ldr r1, =0xaa2
str r1, [r0]
Just these lines alone in crt0.S
will take a full startup from rising edge of reset to MicroPython toggling a pin from ~200ms to ~50ms.
So some way to set the ROSC would be another great addition to Pico SDK if a mode configurable startup is on the table.
Using the ROSC is mentioned briefly in #745 ?
Some more data for the finer-control-over-runtime case- https://github.com/pimoroni/badger2040/issues/10
Just having some weak ref empty functions that are called at various stages of boot would be handy as hooks to avoid having to replace entire portions of the runtime.
We have a few applications of the RP2040 chip and Pico W-as-a-SOM where it's important for us to:
When writing a basic program in C++ it's possible to assert a pin and get the startup GPIO state some 15ms after a cold boot, simply by doing it in the top of
main
, but this depends on there being absolutely no preinit/init happening beforemain
is reached.In real-world scenarios there could be large quantities of zero init BSS (MicroPython for Pico W's 166k
gc_heap
) or initialized SRAM which - in our tests - can move any existing methods of hooking into early startup to some 150ms after the rising edge of RESET. This is enough to miss even a user button press, much less a transient pulse from a hardware peripheral.We can do better by modifying
crt0.S
to init the RP2040 peripherals before SRAM load and zeroing the BSS. This is achieved by splittingruntime_init
intoruntime_init
andruntime_reset_peripherals
the latter of which is called before BSS and SRAM init, immediately followed byruntime_user_init
(this is a very rough proof of concept) which latches ourVSYS_EN
.This takes a (MicroPython PicoW) 150ms time from rising edge of RESET to VSYS_EN_PIN HIGH right down to about 8ms, beating even a vanilla C++ example with code in
main
.Why? In our application
VSYS_EN
must be held high for the Pico W to be powered. We're shutting the chip fully down and powering it back on with a mix of external events. We'd like to know what event "woke" the chip, even if it's transient. Down to a limit, of course. And bearing in mind the chip is off so interrupts et al are no go.To summarize:
I imagine this being configured with something like
-DPICO_STARTUP_PIN_STATE
and-DPICO_STARTUP_PIN_MASK
so a build can be configured with any permutation of (not system essential) pins set to a desired state. This may include pulls but should probably only focus on SIO.For the programming minded (or those who want to deploy this themselves) here's a diff showing my changes to
runtime.c
andcrt0.S
: