RP2040 not starting - How to set adjust the startup delay for crystal stability on custom designs

I have a custom RP2040 based PCB that basically matches the reference design.

Trying to load a “blink” program, it uploads fine, but doesn’t seem to run. The program works fine on an official Pi Pico. I clearly have a working USB connection with the custom board’s RP2040 because it pops up as a UF2 drive and code can be uploaded.

The currently suspected problem is that my crystal design isn’t quite optimal and it’s taking more than the 1ms default to achieve stability. There are suggestions online to set PICO_XOSC_STARTUP_DELAY_MULTIPLIER to a value higher than the default value of 1 (usually 64) to fix this startup stability issue.

Looking at the official code that uses this #define, it should be possible to change that value. Trying a large value however doesn’t trigger the #error so I’m confident this code is not being built with the specified flags - otherwise we’d see a compilation error.

So, where is PlatformIO’s RP2040 platform getting its crystal startup code? I’m not seeing anything relating to xosc in the platform’s sources (or much source code at all). I’m suspecting libs/libmbed.a is a precompiled startup library that has the setting I’m interested in adjusting baked in. Thought I’d ask here before diving into that too much more.

The official platform only supports the Arduino + Pico combination, and the Arduino core is the mbed-based one (GitHub - arduino/ArduinoCore-mbed) with a precompiled version of mbed-os and the variant code (for the Pico) under static settings. Since I don’t see PICO_XOSC_STARTUP_DELAY_MULTIPLIER there, it will likely had its default value. Since the library is precompiled that means that setting that macro after the fact (with e.g. build_flags = -DPICO_XOSC_STARTUP_DELAY_MULTIPLIER=64) does not have any effect since the sources that use this are not recompiled.

There exists an alternative Arduino core from Earle Philhower (Arduino-Pico), but it also uses a precompiled libpico.a where the SDK is precompiled. However, there it looks easier to regenerate that library based with this script.

The easiest way to test your theory is to use PlatformIO with a different platform, namely GitHub - Wiz-IO/wizio-pico: Raspberry Pi Pico development platform for PlatformIO. It has direct Pico SDK support where it builds everything from source, and so you can easily play around with the flags.

As the wiki says, you should first install the platform, then create a new Pico + Arduino project as before, then overwrite the platformio.ini to

platform = wizio-pico
board = raspberry-pi-pico
framework = baremetal
; adjust COM port
monitor_port  = COM1            ;[macOS] /dev/cu.usbmodem0000000000001  ;[Linux] ?
monitor_speed = 115200

build_flags = 

(see config options) and use this as src/main.c (not main.cpp)

1 Like

This is exactly what I was hoping for! Thank you so much @maxgerhardt.

Indeed it was as simple as:

  1. Install wizio’s platform via PIO HomePlatformsAdvanced Installation
  2. Update platformio.ini
  3. Replace main.cpp

And I was able to confirm changes to PICO_XOSC_STARTUP_DELAY_MULTIPLIER work. (Extreme values cause an error, change in behavior on Pi Pico).

Unfortunately, still no luck on my custom board…

Looking into low level QSPI comms at the flash IC, I saw some weird/unexpected behavior: 2.8V on VCC at times and no data on MOSI… Somehow I managed to break the pads on my board. Maybe some low quality copper bonding in that area of the PCB?

Fixing those connection issues, I plugged it in, and it works! Looks like this was the issue the whole time as the standard Arduino based blink works now too.

For those that run into this issue in the future, just because a flash via UF2 claims to be successful, doesn’t mean it’s fully working!

In my case, it seems likely it programmed successfully because it ran after fixing the connections. Maybe because it programs with a slower/lower power method than the normal runtime uses?

1 Like