Twiddling bits in registers doesn’t make the most intuitive, readable, or portable code. This is why we write drivers. I’ve created three Alire packages, rp2040_hal, pico_bsp, and pico_examples. rp2040_hal contains all of the drivers for the chip’s internal peripherals, pico_bsp contains some details about the Pico board and drivers for the Pimoroni Pico addons, and pico_examples contains, you guessed it, example code. At the moment, pico_bsp cannot be used with the Ravenscar runtime without modification, so I’ll ignore that and focus on rp2040_hal for right now. The examples repository contains lots of code that uses the pico_bsp if you’d like to see how that works.

Now that I have drivers, I’ve removed all of the interfaces generated from SVD from our project. These still live in the rp2040_hal package but as long as the drivers implement all of the right interfaces, we shouldn’t need them. If you find something you can’t do with the HAL drivers that seems important, please send a pull request to the rp2040_hal repo. I’ve refrained from tagging a 1.0 release because I’m still not satisfied with all of the interfaces and retain the right to break the API.

with Ada.Real_Time; use Ada.Real_Time;
with RP.GPIO; use RP.GPIO;

procedure Main is
    LED        : GPIO_Point := (Pin => 25);
    Next_Blink : Time := Clock;
    LED.Configure (Output);
       delay until Next_Blink;
       Next_Blink := Next_Blink + Seconds (1);
    end loop;
end Main;

You can see that the Main procedure is much more compact and readable now. The PADS_BANK and IO_BANK stuff is wrapped up in a lovely Configure interface and the GPIO is abstracted into an object with a very convenient Toggle method.

Building the code is done using Alire now, rather than calling gprbuild directly. Alire is analogous to Rust’s Cargo or Python’s pip. Alire keeps track of all of the dependencies and can pull in new ones with the alr with command.

git clone
cd 04-hal-blink
alr build

Source code