rp2040_hal is a library of drivers for the Raspberry Pi RP2040 microcontroller written in Ada.

It’s been 11 months since the first Ada code running on an RP2040 blinked an LED. In that time, rp2040_hal has grown considerably, with support for a veritable alphabet soup of peripherals; UART, SPI, I2C, USB, DMA, PWM, PIO, RTC, Timer, and ADC.

I’m pleased with the state of things and feel like rp2040_hal is a solid foundation for other projects to build upon. Up to this point, each release came with exciting new features and functionality. This release marks a new stage of development, where the focus is on providing bug fixes, performance improvements, and a stable API. In the words of Linus, "We do not break userspace."


If you have questions about Ada, the RP2040, or just microcontrollers in general, come join the conversation at ada-lang/raspberrypi-pico on gitter.im. Gitter.im is available over Matrix if you’d prefer to bring your own chat client.


I often share what I’m working on via on Twitter @JeremyGrosser. I’ve embedded some tweets about my RP2040 Ada projects below.

Changelog 1.0.0

New features

DMA IRQ management

RP.DMA can now configure interrupt masks for each DMA channel. If DMA_Configuration.Quiet = False, the interrupt will fire when a transfer is completed.

Unit tests

We’ve begun writing tests for rp2040_hal with the AUnit Testing Framework. Currently, there are tests for Clock, UART, SPI, GPIO, and DMA. These tests have already led to several bug fixes and we will continue to work toward more complete unit test coverage.

Bugs fixed

GPIO.Mode returned incorrect values

GPIO.Mode was returning the mode of the wrong pin.

PWM divider edge cases

The minimum and maximum PWM divider values were calculated incorrectly. The calculation and constraints on RP.PWM.Divider have been fixed.

RP.DMA.Status returned incorrect Transfers_Remaining

The DMA alias register layouts were incorrect. The only visible effect of this error was that RP.DMA.Status returned an incorrect value for Transfers_Remaining.

Some DMA triggers didn’t work

The DREQ register values did not have a representation clause specified, which caused triggers internal to the DMA peripheral (pacing timers and permanent triggers) to be nonfunctional.