Help Flashing Klipper to Adafruit Feather RP2040?

Hello,

I purchased an Adafruit Feather RP2040 to use with an Adafruit ADXL 343. I got everything wired up, and have now found that the boot.uf2 that’s made with make menuconfig setup for the RP2040 won’t work with the feather RP2040 because it uses a different flash chip (GitHub Issue link). I’ve read through the lib/rp2040/boot_stage2/ directory, which Kevin O’Connor references as being the place to modify to get this to work and cross-referenced it with Adafruit’s CMakeLists.txt on their GitHub (link) and it seems that I need to set the boot_stage2 file to be boot2_w25qs080.S . There is a boot2_w25q080.S in the boot_stage2/ directory, but I couldn’t get it to work, and I think the “s” may be significant between the two.

I tried setting #define PICO_BOOT_STAGE2_CHOOSE_W25Q080 0 from 0 to 1 in boot_stage2/config.h (line 31) and rerunning make but the resulting UF2 file doesn’t make my board present in the list of USB devices.

Has anyone done this successfully before? I recognize now that non-2mb flash RP2040 boards aren’t explicitly supported, but if there’s a configuration change I can make it the code to build a compatible firmware, that would be great.

Thanks!

Quick update, I ended up doing some more digging and found the board config file on the rp2040 sdk for the feather 2040 (link). It doesn’t use the W25Q080.S like I thought it did. It’s defined to use GENERIC_03H.

I went into my RPi’s klipper install and undid my change to boot_stage2/config.h, instead editing the Kconfig and Makefile in the rp2040 src directory. I changed the boot2 file and flash size to match the feather.

I then tried building and unfortunately the boot2_generic_03h.S file references a non-existant file - pico/asm_helper.S - That looks to be this file in the pico-sdk. I’m not exactly sure where the correct place to add this file within the directory structure, and it references a pico.h, which I’m not sure is present either.

It seems like getting this to build should be a solvable problem, though I think I’m probably doing it “the hard way” like this. My lack of familiarity with CMake is painfully obvious, I’m sure. Anyway, this is as far I as I got before calling it a night tonight. I’ll try to keep documenting my findings in this thread in case someone else comes along and wants to use a non-pico, non-2mb flash, rp2040 board.

For the boot2_w25q080.S file, I only needed to comment out the include for asm_helper.S as nothing in the assembler actually used anything from that file. It’s possible boot2_generic_03h.S is the same.

-Kevin

I’ll give that a shot, thank you!

That worked! After a reboot of my Pi, I can now see it in the /dev/serial/by-id/ directory and talk to it via klipper. Thank you!

To summarize the steps I took for flashing an alternative RP2040-based board:

  1. Find your boards header file in the Raspberry Pi SDK Github (github DOT com/raspberrypi/pico-sdk/tree/1.2.0/src/boards/include/boards)
  2. Find the section for the flash definitions (commented FLASH) and get the values for the type of flash used, SPI clock divider, and flash size in bytes In my case these were were defined as PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1, PICO_FLASH_SPI_CLKDIV 4, and PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
  3. Move to your Pi’s terminal and head to the ~/klipper/src/rp2040/ directory. You’ll need to edit the Kconfig and Makefile files.
    3a. In Kconfig - Edit the FLASH_SIZE to match the value after PICO_FLASH_SIZE_BYTES. This value is in hexadecimal, so 2mb is 0x200000 and 8mb would be 0x800000. Save & exit.
    3b. In Makefile - Edit file referenced on line 27, below the comment # rp2040 stage2 building to match your board header file. In my case I edited it from boot2_w25q080.S to boot2_generic_03h.S. The file you should use is the one specified in this statement from the board header file: PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H. These boot_stage2 files are located at ~/klipper/lib/rp2040/boot_stage2/
    3c. Also in Makefile - Edit the -DPICO_FLASH_SPI_CLKDIV=__ flag, at the end line 29 to match your PICO_FLASH_SPI_CLKDIV definition from the header file. In my case this was CLKDIV=4. Save and exit Makefile.
  4. Move to the ~/klipper/lib/rp2040/boot_stage2/ directory and edit your boot2_XXX.S file, that you specified in step 3b. You’ll need to comment out the line #include "pico/asm_helper.S". Save and exit.
  5. Move to the ~/klipper/ directory and run make clean and then make. This will build your rp2040.uf2 boot file. You can then flash it using a separate computer, by copying the .uf2 to that computer over scp, and moving to step 6. You can also use klippers make flash SERIAL_DEVICE=XXX_XXX, if you know your RP2040’s serial id.
  6. If you’re flashing on a separate computer, load the .uf2 onto your rp2040 by plugging the board in with the boot select button (boot_sel) pressed. The board should show up on your computer as a usb drive. You will then need to put the .uf2 onto the root directory of the drive, and it should cause the board to reboot.
  7. If you used a separate computer to flash, plug the board into your pi and look for it’s id using the command ls /dev/serial/by-id/*. If it doesn’t appear, try rebooting your pi (sudo reboot now) and checking again.
  8. Now that you have the pi visible in the serial devices, it should be ready to define in your Klipper config, as an [mcu]

Thanks. Can you grab the code at Add support for rp2040 "generic_03H" flash chips by KevinOConnor · Pull Request #5588 · Klipper3d/klipper · GitHub and verify that everything works if you select “low level options” and “generic_03h” flash from Kconfig?

-Kevin

Yeah I can pull that branch onto my local, re-flash and report back. Is there anything like a diagnostic sweep I can run to check that everything on the RP2040 is functioning as expected? I’ve been working under the assumption that if I flash and it boots correctly and is recognized by Klipper, then it’s good to go.

@koconnor I just tried flashing my Adafruit Feather RP2040 with that branch, and it appears to have worked as expected. I used the built-in make flash FLASH_DEVICE=XXX_XXX to flash the board as well. The only thing of note was that I needed to reboot my Pi for the for the newly flashed RP2040 to show up in the serial devices list.

If there are any other tests I should run, please let me know.

Thanks. As far as I know, this low level code either “works fully” or “doesn’t work at all”. So if you got it to boot then I think it indicates success.

Cheers,
-Kevin

Awesome! Thank for working to add this support to the main codebase.

One interesting behavior is that if I disconnect and reconnect the rp2040 board, by unplugging the USB cable, I have to restart my Pi for it to be visible in the /dev/serial/by-id/* device list. This doesn’t match the behavior of my Einsy RAMBO, which is immediately re-recognized. Does this match up with how the Pi Pico behaves?

Also, I’d be happy to go through the RP2040 boards defined in the SDK and create configs for them within Kconfig, so that users could choose their board instead of needing to look up which SPI flash module their board has on it. I think this would be a lot more straightforward for Klipper’s less technical users.

FYI, I committed the rp2040 Kconfig settings to the master Klipper branch.

That doesn’t occur for me, but it doesn’t sound like it is related to the micro-controller type. Sounds like something odd at the OS or USB wiring level.

Last I looked there was just the two adafruit boards that used generic_03h (at least as defined in the pico sdk). I’d guess those two boards aren’t particularly common, but if you’ve got a better way to describe it in Klipper then feel free to submit a PR.

Cheers,
-Kevin