Raspberry Pi RP2350

Raspberry Pi released some new silicon today, RP2350.

I’m currently busy with my C compiler work, but I figured I’d write up some of my thoughts.

There are a few options for running Ada on this chip. These options are not mutually exclusive, but as a small community it seems like we should focus our resources on one or two options.

Peripheral drivers

  1. Update rp2040_hal to support the new chip, changing the API as little as possible. This means existing drivers are likely to work, but will miss some of the fancy features of the new chip.
  2. Write a new rp2350_hal crate to implement the HAL interfaces on this chip using SVD definitions.
  3. Write bindings to the Raspberry Pi C/C++ SDK and statically link it.

Runtimes

  1. Port @simonjwright’s FreeRTOS-Ada runtime to RP2350. Could use the RISC-V cores on the new chip and share some code with the ESP32 port. Might integrate better with the Raspberry Pi SDK.
  2. Port bb-runtimes to RP2350. Probably the best option if we want to explore the new security features of the chip.
  3. Build examples using @Fabien.C’s bare_runtime that do as little as possible, leaving everything up to the user.
  4. Use some other RTOS like Zephyr or RTEMS.
3 Likes

I am a bit disappointed by the clock speed, and I’d would love to know why on earth you put both ARM and RISC-V cores on the same chip!?! But overall it looks like an amazing upgrade.

  • 2 x Cortex-M33 :partying_face:
  • Double the RAM :partying_face:
  • Support for 2 flash or flash + RAM :partying_face:
  • Hardware TMDS Encoder + HSTX for DIV/HDMI output :partying_face:
  • USB White-Labelling is nice (change USB product and device ID even when booting in UF2 mode).
  • Bootstrapping a flashless RP2350 from a simple host, such as another
    microcontroller. This plus the DVI output makes the RP2350 a nice embedded “GPU”

From what I can see there’s not much change in terms of peripherals. It should be straightforward to add support from the rp2040_hal.

I’ve seen comments saying it runs reasonably stable up to 300 MHz, seems fast enough for me.

It sounds like the RISC-V cores didn’t cost much die area and it provides a nice way to A/B test code against ARM to see if a more complete transition to RISC-V in the future makes sense. I love that the core itself is open, there’s Verilog on GitHub!

Really happy to see support for atomics, should simplify SMP use cases.

External RAM opens up a lot of possibilities. Somebody’s definitely gonna run Linux on this.

The boot ROM has a lot more functionality, it’s going to take some thinking to figure out how best to transition the startup and linking parts of rp2040_hal.

Just to put another idea out there: Maybe we could build on top of the Rust rp-rs project?

There’s a blog post about their progress.

I’m unable to report progress on the FreeRTOS-Ada port to ESP32-H2 (GPIOs in general work, but I can’t get GPIO interrupts), so unless the query I raised with Espressif comes up with an answer I’ll probably shelve it in favour of this chip.

Breaking news: ordered! from Pimoroni.

I’ve got a few Pico 2 boards on order, but as far as I can tell, no US distributor has it in stock yet. A few people got preproduction samples and the first 30,000 chips out of the factory went on DEF CON badges. I think I heard Luke Wren say they’ve got another 100k chips shipping in September, ramping up to higher volume from there.

So, it’ll probably be a few months before we can all play with it.

I’ve got my board! (just the one).

You’ll know how unrewarding it is to bring up an RTOS on a new chip if you don’t have a working debugger. RPi’s documentation is a little unhelpful about what you need in OpenOCD’s setup; this issue is where I’ve got to. OK, using a Segger J-Link is maybe a little unusual, but as you can see it works fine for the arm cores.

I also tried an STLINK/V2 and an STM32F4, both of which support SWD, but OpenOCD says they don’t.

Maybe try updating the firmware on your J-Link?

I usually just use a spare Pico board with the picoprobe firmware.

The J-Link firmware was up-to-date.

I was trying to get away with kit I have to hand; will have to get a Pi Debug Probe (or perhaps a Pico, but that would be less convenient).

ISTR that connecting to the riscv core requires the debug probe to load some code to the 2350?? which might be a bit advanced for the cortex-m oriented probes such as J-Link.

I think that the problem is that the board defaults to arm, so when the debugger tries to talk to a riscv core it ain’t there.

I found a riscv UF2 file; uploaded it to the board; started openocd; it connected!!

I guess the immediate fix is to find an OTP setting that forces at least core 0 to riscv. I really dislike one-time programming.

1 Like

It looks like the reboot ROM function takes a flag indicating which core architecture should be used. I wonder if there’s a way to have OpenOCD detect if it’s running in ARM mode and load a little bit of code to call that ROM function with the REBOOT_TO_RISCV flag.

There’s an OTP flag to do with this. Section 3.9 of the datasheet says

The default and allowable values of the ARCHSEL register are determined by critical OTP flags:

  1. If CRIT0_ARM_DISABLE is set, only RISC-V is allowed.
  2. Else if CRIT0_RISCV_DISABLE is set, only Arm is allowed.
  3. Else if CRIT1_SECURE_BOOT_ENABLE is set, only Arm is allowed.
  4. Else if CRIT1_BOOT_ARCH is set, both architectures are permitted, and the default is RISC-V.
  5. If none of the above flags are set, both architectures are permitted, and the default is Arm.

No CRIT1 flags are set by default, so on devices where both architectures are available, the default is Arm. To change the default architecture to RISC-V, set the CRIT1_BOOT_ARCH flag to 1.

Looks like CRIT1_BOOT_ARCH is the thing, though I can’t quite make sense of the above vs. the description of ARCHSEL in Table 1352.

OK, I got Ada.Real_Time.Clock and delay until working. The trick was to use the correct -march setting.

In the Datasheet’s discussion of the MISA register, it says that the ideal -march string is rv32ima_zicsr_zifencei_zba_zbb_zbs_zbkb_zca_zcb_zcmp, but if your toolchain doesn’t support the Zc extensions (GCC 14.1/binutils 2.42 don’t) use rv32imac_zicsr_zifencei_zba_zbb_zbs_zbkb. I had been using the settings from my esp32h2 attempt, rv32imac_zicsr_zifencei, but with them - no clock interrupts!

Now for some blinkenlights.

1 Like

There’s an article about using the RISC-V core of the RP2350 on CNX-Software.

1 Like

Another interesting CNX Software article :

I started porting rp2040_hal to RP2350, but it’s kind of a mess… I made a lot of assumptions in that library that don’t hold for the new chip and requires a rewrite of many of the drivers.

So I started on a new rp2350 library, mostly minimal type definitions for the registers I actually need, and linker/startup scripts. I’ve found the SVD types aren’t generated the way I want most of the time, so I’m just going to do the type definitions by hand. These are declared in Pure packages that should be portable to both CPU architectures and independent of any driver implementations. Some of these might be portable to RP2040 too, but I’m not too worried about that right now.

I’m making an effort to do everything with SPARK_Mode => On where possible.

I’ve got an LED blinking with both the Cortex-M33 and Hazard3 cores, though I haven’t implemented a timer for Hazard3 yet.

5 Likes

Nice :+1:

I would love to have more info on this. From my quick read of the documentation I felt like most of the peripherals are backwards compatible if not completely identical.

The peripherals are mostly similar, though most of them have added fields. For example, PADS_BANK has a new ISO flag that needs to be cleared to use a GPIO pin. Many registers are now extended to 64 bits to support higher pin count packages. This complicates many Volatile_Full_Access registers.

The boot2 and flash code are very different from RP2040. There are alternate versions for the RISC-V core too.

I’m not saying it’s impossible to get rp2040_hal working on the new chip, but it’s going to be a lot of refactoring and conditional compilation. I pushed my changes to the rp2350 branch if you want to poke at it, but it’s not really in a usable state.

In case you didn’t know : The Worsening Raspberry Pi RP2350 E9 Erratum Situation | Hackaday

I see I cleared the ISO flag without realising it was different from the 2040.

Are you sure about 64-bit registers? I didn’t spot any, they seem to use 2 32-bit registers (e.g.

   type TIMER0_Peripheral is record
      --  Write to bits 63:32 of time always write timelw before timehw
      TIMEHW   : aliased RP2350.UInt32;
      --  Write to bits 31:0 of time writes do not get copied to time until
      --  timehw is written
      TIMELW   : aliased RP2350.UInt32;
      --  Read from bits 63:32 of time always read timelr before timehr
      ...

My problem is that within 10 or so key presses (which generate interrupts on any edge) I get an access violation when the ISR completes and attempts to return to the idle task.

I should add that I’m using the Xh3irq extension, which allows up to 512 interrupts (well, I suspect it’s actually 128, because there’s a 4-bit priority value which needs to be fitted into a 512-bit array in the Hazard3 chip’s internals). That makes 4 interrupt-handling mechanisms I’m aware of (including the basic one, which funnels all external interrupts down one channel).