zmkfirmware/zmk

rp2040 (raspberry pi pico) support tracking issue

Opened this issue ยท 35 comments

Adding this as a spot for folks to track the work to support rp2040 based boards.

There is upstream effort to support the SoC in zephyrproject-rtos/zephyr#34835 and on top of that, @protobits and I have added USB, SPI, UF2, etc support so far.

Notes

  • This won't be officially supported until an official Zephyr release supports this, and we have upgraded to that version. As such, this is still months away.
  • Experimental work will be shared here, but no end user support will be provided yet; I simply don't have the bandwidth. Only try to use this if you know what you're doing, please!

Current Status

Super experimental ZMK branch building against Zephyr main + ZMK changes + rp2040 enhancements supports:

  • Build and flash UF2 images.
  • GPIO, with interrupts,
  • USB, but this is flaky still. Multiple endpoints fails, some errors/delay in startup from it.
  • SPI, but the hardware doesn't support LSB mode, so sharp displays not working yet.
  • UARTs work.

Not anywhere near supported

  • Wired split
  • RGB (ws2812 and friends)
  • OLEDs (no I2C driver yet)

I have board definitions for the kb2040 and the Qt Py 2040, and upstream author added the pico board.

Where To Get It

My personal ZMK fork has a core/zephyr-main-rp2040-playground branch which includes the Zephyr 2.7 upgrade work plus a few additional changes.

It relies on my personal Zephyr fork, petejohanson/zephyr, branch is main+zmk+rp2040

Doing west update after you grab the ZMK branch should work.

Hi, Found you from the base Issue. My thanks for the work you've put in.

I'm looking at this PR because I'm wondering whether Zephyr will be suitable for my RP2040 project, which uses about 80% of the blocks in that mcu. I don't know enough about Zephyr, but I will also need to use the PIO devices - how would that fit into Zephyr's device structure?

You could potentially get around the SPI LSB issue by using a PIO block to create an alternate SPI interface - the pioasm code for it is around and I presume could be adapted as needed. Ditto for the WS8212 driver.

I found the library 'u8g2' on github which is what looks like a really great LCD/OLED driver for MCUs. Would that be suitable for Zephyr? It supports loads of devices, many fonts, character, mono and greyscale graphic output, SPI and I2C. I would expect that the latter may be an issue (porting needed?) My need is to drive a Surenoo 320x132 greyscale OLED which uses the SSD1320Z driver chip.

Hi, Found you from the base Issue. My thanks for the work you've put in.

I'm looking at this PR because I'm wondering whether Zephyr will be suitable for my RP2040 project, which uses about 80% of the blocks in that mcu. I don't know enough about Zephyr, but I will also need to use the PIO devices - how would that fit into Zephyr's device structure?

I haven't looked closely enough at the PIO stuff to see how that would fit into the build tooling for Zephyr, but in theory it shouldn't be hard to make work.

You could potentially get around the SPI LSB issue by using a PIO block to create an alternate SPI interface - the pioasm code for it is around and I presume could be adapted as needed. Ditto for the WS8212 driver.

Indeed. It's on my list to explore.

I found the library 'u8g2' on github which is what looks like a really great LCD/OLED driver for MCUs. Would that be suitable for Zephyr? It supports loads of devices, many fonts, character, mono and greyscale graphic output, SPI and I2C. I would expect that the latter may be an issue (porting needed?) My need is to drive a Surenoo 320x132 greyscale OLED which uses the SSD1320Z driver chip.

Zephyr has it's own display driver stack, we use along with LVGL in ZMK, often with ssd1306 displays. It shouldn't be hard to implement a driver for that if one doesn't exist yet. Check the drivers/display/ folder in Zephyr.

I have done some work on the port, two commits in rivimey/support_raspberrypi_pico

925c6bcd7d : adds most of the pinctrl definitions for the RP2040 to rpi-pico-rp2040-pinctrl.h

0cf92bc279f : adds the "Solderparty RP2040 Stamp" board (and not the carrier board for it), though it is not yet complete and will need more work.

The latter includes solderparty_rp2040_stamp.dts where I have started to flesh out the DTS definitions for the pinctrl pin defines (in solderparty_rp2040_stamp-pinctrl.dtsi and rpi_pico-pinctrl.h)

I have probably made some mistakes in all this and am will continue working on it, but I wanted to let you know it was happening.

If you want a pull request that's ok, but in addition to the above I have rebased yonsch's work onto (nearly) the current 'main' branch. The rebase was easy so it won't be a problem to cherry-pick back again.

I have done some work on the port, two commits in rivimey/support_raspberrypi_pico

925c6bcd7d : adds most of the pinctrl definitions for the RP2040 to rpi-pico-rp2040-pinctrl.h

Excellent!

0cf92bc279f : adds the "Solderparty RP2040 Stamp" board (and not the carrier board for it), though it is not yet complete and will need more work.

The latter includes solderparty_rp2040_stamp.dts where I have started to flesh out the DTS definitions for the pinctrl pin defines (in solderparty_rp2040_stamp-pinctrl.dtsi and rpi_pico-pinctrl.h)

That's awesome, this was on my list since I just got a stamp and carrier board built this week. Will definitely test that.

I have probably made some mistakes in all this and am will continue working on it, but I wanted to let you know it was happening.

If you want a pull request that's ok, but in addition to the above I have rebased yonsch's work onto (nearly) the current 'main' branch. The rebase was easy so it won't be a problem to cherry-pick back again.

I'm not sure, at some point this all needs to be nicely discrete PRs to Zephyr. My work is more intended for playing than long term use. I'm happy to take in your work, but ideally you'd have in mind submitting those.piece there when the core PR hits.

Update: Upstream zephyrproject-rtos/zephyr#34835 was merged just now, and that will be in Zephyr 3.0 that will be released "soon"

That's just the core board + infrastructure w/ GPIO + UART peripherals, no USBD yet, so when ZMK upgrades to Zephyr 3.0 (we'll likely skip 2.7 which I've been testing a lot lately), we'l be mostly there.

If/when things like the USBD driver get accepted into Zephyr, I will likely cherry pick them forward into our Zephyr branch, so we can hopefully have this usable on top of Zephyr 3.0.

I've rebased my main+zmk+rp2040 Zephyr branch on top of latest Zephyr main, including the recently merged Pico base work, and refactored things to match the naming conventions they settled on for vendor prefix, etc.

I've also rebased my core/zephyr-main-rp2040-playground ZMK branch on top of latest ZMK main to bring it up to date.

I will be focusing on the USB device driver next, trying to get that fixed to be really usable generally, before getting that upstreamed.

Ok, I found and fixed the on major issue w/ the USBD driver that was causing hangs on initial start and USB setup w/ hosts. The driver is now up in a PR for Zephyr zephyrproject-rtos/zephyr#42506 and has had one round of review and feedback.

Seems to be working fairly well, and I've rebased the main+zmk+rp2040 branch to incorporate that latest driver work for anyone looking to test.

@petejohanson I see there are a few changes requested, is there anything anyone can do to help?

@petejohanson I see there are a few changes requested, is there anything anyone can do to help?

If you're talking about the USB device PR, just had other stuff on my plate. I've pushed all of the suggestions this AM for review again.

Made some great progress on a couple small tweaks to the USB driver last night, which fixed my major issue with not having USB logging work at all.

My current test keeb is now much better, although I've encountered one or two lock ups still, so not quite ready for prime time.

Peter, I emailed you a few days ago; sorry if that was unwanted, but if you could assist I would be very grateful.

Ok, so I've done a ton of work to improve the USB driver, I'm typing this right now from an QT Py RP2040 powered Zaphod Lite!

I've created a ZMK/zephyr branch users can follow the https://zmk.dev/docs/features/beta-testing/ guide to test with. You'd end up w/ a west.yaml:

manifest:
  remotes:
    - name: petejohanson
      url-base: https://github.com/petejohanson
  projects:
    - name: zmk
      remote: petejohanson
      revision: hardware/rp2040-support
      import: app/west.yml
  self:
    path: config

Supported controllers:

  • rpi_pico
  • adafruit_kb2040
  • adafruit_qt_py_rp2040
  • sparkfun_pro_micro_rp2040
  • seeeduino_xiao_rp2040
  • boardsource_blok

I have some XIAO RP2040 controllers on the way here, will be adding a board definition for them soon.

You can see a sample build run using this approach at https://github.com/petejohanson/shared-action-zmk-config/tree/rp2040

IMPORTANT

Wired split is not supported yet, so only suitable for testing w/ unibody boards like reviung41, etc.

Tested

  • Basic matrix use. I have encountered some slight funkiness on one of my two RP2040 keyboards requiring adding some tiny matrix scanning delay. Code is in that branch, and it's not enabled by default, but necessary pending further investigation.
  • SPI driver is working fine, Zaphod Lite prototypes use an SPI expander without issue. The SPI chip in the RP2040 doesn't support MSB mode, so sadly, the sharp memory display driver does not work.
  • USB, including USB logging.

Untested

  • An rpi_pico based keyboard.
  • A sparkfun_pro_micro_rp2040 keyboard. I have the hardware, just haven't had a chance to test.
  • I2C code is here, merged from Zephyr main, but I haven't gotten it tested yet. Will hopefully do that next day or two w/ an SSD1306 display.

Anyone testing, please report back here w/ success or problems.

Thanks!

Tested and fixed the I2C driver. I can now get a working ssd1306 display on rp2040.

The rpi_pico board definition provided by this branch is working fine for me on my macro pad. Not doing any i2c or anything, just standard keycodes/behaviors.

USB driver work has been merged upstream: zephyrproject-rtos/zephyr#42506

Lots of additions have made into what will be Zephyr 3.1. There's a proper i2c driver that someone else contributed, which I would like to pull forward, instead of using the less-official one I had implemented. There's also an open SPI driver that I want to test that's more likely to end up upstream as well: zephyrproject-rtos/zephyr#45131

Nice work, everyone!

hi! nice job!
thank you very much!

@petejohanson

Wired split is not supported yet, so only suitable for testing w/ unibody boards like reviung41, etc.

any chances of getting wired split?

hi! nice job!
thank you very much!

@petejohanson

Wired split is not supported yet, so only suitable for testing w/ unibody boards like reviung41, etc.

any chances of getting wired split?

There will be eventually, but that will be a seperate effort from this work. The RP2040 work will be included in the Zephyr 3.2 upgrade that is being worded on.

There's a separate PR already open that's starting the work on split wired support, that will need to be completed as well.

seeing as there's now (beta) support for bluetooth 5 in the pico w, any thoughts on how long it would take to have Bluetooth working as well?

seeing as there's now (beta) support for bluetooth 5 in the pico w, any thoughts on how long it would take to have Bluetooth working as well?

Zephyr has their own entirely separate OSS BT stack, so it's unlikely much, if any, of the work in the pico SDK for BT would be used or relevant. I did spot this open PR for Zephyr that's more likely to be the start of supporting this eventually: zephyrproject-rtos/zephyr#55014

Unfortunately zephyrproject-rtos/zephyr#55014 is specifically for H4 transport (that is, module connected via UART with flow control signals). That is not how the module is wired on the Pico W, it looks like that may need a custom HCI transport driver with PIO support. There is a PR to support PIO though, so that may be possible at some stage.

What's the latest status of rp2040 support?

There's a PR under review to add SPI via PIO support (zephyrproject-rtos/zephyr#60395). This is not immediately what the wireless module needs (zephyrproject-rtos/zephyr#60395 (comment)), but it's one step closer.

From the official blog Pi Pico & rp2040 friends seem now supported...

Raspberry Pi Pico/RP2040 Support

This Zephyr update allows ZMK to support the new(-ish) RP2040 SoC found in the Raspberry Pi Pico.
note

ZMK does not support wired split communication yet, so RP2040 is only usable for non-split keyboards. To follow progress on wired splits, see #1117.
Supported Controllers

The following RP2040 powered controllers have board definitions for folks to test:

Raspberry Pi Pico (rpi_pico)
SparkFun Pro Micro RP2040 (sparkfun_pro_micro_rp2040)
Adafruit Keyboar/KB2040 (adafruit_kb2040)
Seeeduino XIAO RP2040 (seeeduino_xiao_rp2040)
Adafruit Qt PY RP2040 (adafruit_qt_py_rp2040)
BoardSource blok (boardsource_blok)
Elite-Pi (compatible with the sparkfun_pro_micro_rp2040 board)

Nice! And what's the status of supporting splits via Bluetooth?

Nice! And what's the status of supporting splits via Bluetooth?

BLE with the pico W is still waiting on upstream Zephyr support, so quite a ways off. But beware the power draw is significant, so battery life will be much shorter than nRF52 based solutions.

Nice work everyone.. any update regarding BLE split keyboard connection?

Nice work everyone.. any update regarding BLE split keyboard connection?

Is there anything that wasn't clear from my reply here? #1085 (comment)

But beware the power draw is significant

@petejohanson Is it the character of the Pico W or something that can be optimized later?

I'm going to build a bluetooth split keyboard with Pico because that's the most available board around me.

But beware the power draw is significant

@petejohanson Is it the character of the Pico W or something that can be optimized later?

I'm going to build a bluetooth split keyboard with Pico because that's the most available board around me.

It's an unavoidable fact of the draw of hardware itself. The rp2040 chip draws a fairly large amount even when idle, and then there is another chip that is responsible for the wireless comms that also draws power on top of that.

So, whenever Zephyr fully supports the integration with that secondary chip, these should be usable with ZMK, but you'll need a much larger battery when using them to get a reasonable runtime from them.

From the official blog Pi Pico & rp2040 friends seem now supported...

Raspberry Pi Pico/RP2040 Support

This Zephyr update allows ZMK to support the new(-ish) RP2040 SoC found in the Raspberry Pi Pico.
note

ZMK does not support wired split communication yet, so RP2040 is only usable for non-split keyboards. To follow progress on wired splits, see #1117.
Supported Controllers

The following RP2040 powered controllers have board definitions for folks to test:

Raspberry Pi Pico (rpi_pico)
SparkFun Pro Micro RP2040 (sparkfun_pro_micro_rp2040)
Adafruit Keyboar/KB2040 (adafruit_kb2040)
Seeeduino XIAO RP2040 (seeeduino_xiao_rp2040)
Adafruit Qt PY RP2040 (adafruit_qt_py_rp2040)
BoardSource blok (boardsource_blok)
Elite-Pi (compatible with the sparkfun_pro_micro_rp2040 board)

Did this break with zephyr 3.2?

But beware the power draw is significant

@petejohanson Is it the character of the Pico W or something that can be optimized later?
I'm going to build a bluetooth split keyboard with Pico because that's the most available board around me.

It's an unavoidable fact of the draw of hardware itself. The rp2040 chip draws a fairly large amount even when idle, and then there is another chip that is responsible for the wireless comms that also draws power on top of that.

So, whenever Zephyr fully supports the integration with that secondary chip, these should be usable with ZMK, but you'll need a much larger battery when using them to get a reasonable runtime from them.

The Pico W might become an excellent choice for a ZMK dongle paired to some low-power split keyboard halves.

The Pico W might become an excellent choice for a ZMK dongle paired to some low-power split keyboard halves.

Yeah, definitely a valid use case for this once supported.

OWL4C commented

So if i understand correctly, the Pico W is working with zephyr, but it needs further work to actually use the wireless chip, so currently pico w = pico from a feature support standpoint, and pico is supported?