Skip to content

Support RP2350 in builder/picosdk, added custom board for testing #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

norandomtechie
Copy link

@norandomtechie norandomtechie commented Apr 1, 2025

Hi all,

Thank you for all your hard work! This is one of my first PRs to the wider open-source community so please let me know if there is anything important I missed.

I am interested in porting over our embedded systems course labs to the RP2350 platform, but we need to use the Pico SDK instead of the Arduino framework. I designed a custom development board + debugger for the RP2350B variant which I would like to develop support for on PlatformIO, which we've used successfully so far for the STM32F091RCT6 custom board we have.

Off the bat, @maxgerhardt's repo didn't seem to compile for the RP2350, so I made some changes to the builder/picosdk script that makes it compile for RP2350 while (hopefully) still maintaining support for the RP2040. I've attached a MVE for reference. Theoretically, this should work with a Pico 2 and the official Debug Probe attached, as well.

pio-test.zip

I also added our custom board (db_rp2350) since none of the other files have picosdk listed as a supported framework.

What works in this commit:

  • Switching between RP2350/RP2040 by using board_build.mcu in PIO options.
  • Build/Upload to our board with the picoprobe option.
  • Basic debugging (inspecting variables, watch statements)
  • ARM-only (will add RISC-V later on)

What I'm having trouble with (that I could use some advice on):

  • UART via our debugger doesn't seem to work even though it works just fine with the Pico extension. My guess is that the necessary libraries aren't getting included properly.
    • Solved further down!
  • SVD file parsing by the Peripherals view while debugging is broken ("TypeError: cannot read properties of undefined, reading 0") which seems to be a widely known issue, not just with the RP2xxx SVDs.

@Jason2866
Copy link

LGTM now.

@maxgerhardt
Copy link
Owner

Very impressive! I will test this on my RP2350 and RP2040 to see if everything still works, and maybe I'll figure out why UART won't won't too.

Thanks @Jason2866 for the review, agreeing in all PR review points.

@maxgerhardt
Copy link
Owner

maxgerhardt commented Apr 1, 2025

It blinks very nicely on both my RP2040 and (Pimoroni Tiny) RP2350.

The hardcoded

# todo: try to better guess the board header name based from the board definition name
# instead of requiring them to explicitly include it
rp2_board_header = board.get("build.picosdk.board_header", "pico.h")

is still a weakness though, and I actually used

board_build.picosdk.board_header = pimoroni_tiny2350.h

to get the right definition for PICO_DEFAULT_LED_PIN in the blinky example. I'll have to write a static lookup table there.

But, one improvement at a time. This can be done in a separate piece of work.

@norandomtechie
Copy link
Author

norandomtechie commented Apr 1, 2025

It blinks very nicely on both my RP2040 and (Pimoroni Tiny) RP2350.

Great to hear it didn't break it!

The hardcoded

# todo: try to better guess the board header name based from the board definition name
# instead of requiring them to explicitly include it
rp2_board_header = board.get("build.picosdk.board_header", "pico.h")

is still a weakness though, and I actually used

board_build.picosdk.board_header = pimoroni_tiny2350.h

How about this? Or should I just make this another branch/PR?

header = "%s.h" % board.get("build.variant")
# try to find the board header in the common directory
if isfile(join(FRAMEWORK_DIR, "src", "boards", "include", "boards", header)):
    rp2_board_header = board.get("build.picosdk.board_header", header)
else:
    rp2_board_header = board.get("build.picosdk.board_header", "pico.h")

@norandomtechie
Copy link
Author

Something I noticed regarding the UART - the problem is not with how the UART hardware is being initialized, but with the underlying syscalls/device driver code connecting printf to the UART peripheral. If I use the UART write function directly as follows, it works:

uart_write_blocking(uart0, "Hello, world!\n", 14);

Similarly, scanf doesn't work either on RX, but the uart_read_blocking call works.

@norandomtechie
Copy link
Author

Figured it out! I just needed to add:

("LIB_PICO_STDIO", 1),
("LIB_PICO_STDIO_UART", 1)

to CPPDEFINES, and printf started working. I'll include these in a new commit.

I also realized I needed to flush the stream before the text would appear on the UART, so I added a \n and it started working.

- Add detection scheme for custom header files
- Add rename_exceptions back for both RP2350 and RP2040
- Added includes for newer SDK versions (tested 2.1.1), sorted in ascending order for legibility
- Fix printf by adding LIB_PICO_STDIO if UART is needed
- Sorted default_common_rp2_components in ascending order for legibility
@norandomtechie
Copy link
Author

I also got a modified SVD file working as well under Peripherals!

image

I compared it to the STM32F0x1.svd we were using and found that the RP2350 one was using bitRange while the STM32 uses bitOffset and bitWidth. I wrote a script that replaced the bitRange fields with those, along with some other fields I noticed from the STM32 one, and it worked for both the RP2350 and RP2040!

Here is the patching script: svd-patcher.py.txt

I wouldn't add the patched SVD files in this PR however, since it has placeholder descriptions for the registers/peripherals that didn't have the fields, just until I can figure out how to get the correct info added for each register bit.

@maxgerhardt
Copy link
Owner

Great! Having a SVD file working is certainly better than having none working at all. The script just shouldn't try to create new information where there was none in the SVD; so if a register has no description, then the output file should also have none. Unless it must have one to be able to be parsed properly.

Is there anything else that you still want to add for this PR?

@norandomtechie
Copy link
Author

The script just shouldn't try to create new information where there was none in the SVD; so if a register has no description, then the output file should also have none. Unless it must have one to be able to be parsed properly.

Fully agreed - I just needed something working for our testers when we write instructions on how to debug in our labs :)

Is there anything else that you still want to add for this PR?

No, I think that's it for now. LGTM and thank you both for your help!

@maxgerhardt maxgerhardt merged commit 2ef15df into maxgerhardt:develop Apr 2, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants