I’ve tagged release 0.5.0 of the rp2040_hal, pico_bsp, and pico_examples libraries for the Raspberry Pi Pico.

In addition to this month’s library updates, I’ve begun making YouTube videos about developing Ada on the Raspberry Pi Pico, starting with a debug setup and serial console library.

rp2040_hal 0.5.0

New features

UART enhancements

RP.UART now allows configuration of baud, word size, parity, and stop bits via the UART_Configuration record. The default values for the UART_Configuration record represent the typical 115200 8n1 setup.

The UART now has a Send_Break procedure, which holds TX in an active state (usually low) for at least two frame periods. Some protocols use the UART break condition to indicate the start of a new packet.

RP.UART.Receive now sets Status = Busy and returns immediately if a break condition is detected.

UART Transmit and Receive procedures now return as soon as all words have been delivered to the FIFO. FIFO status is exposed by the Transmit_Status and Receive_Status functions. This interface is the same as the I2C and SPI drivers.

The uart_echo example has been updated to demonstrate these new features.

RTC driver

The real time clock is now exposed by the RP.RTC package. It implements the HAL.Real_Time_Clock interface for getting and setting the date and time. An example project demonstrates use of the RTC. RTC alarm interrupts are not yet implemented.

Interpolator driver

The RP2040 has two interpolators per core embedded in the SIO peripheral. The RP.Interpolator package make their registers available. Some of the registers in this block support single-cycle operation, so it would be counter productive to wrap them up in procedures that may not be inlined by the compiler. There are examples in the datasheet for working with the interpolators, but I’m still trying to wrap my head around it, so there is no example here yet.

Breaking changes

UART.Enable is replaced with UART.Configure

To match the nomenclature of the other serial drivers (SPI, I2C), RP.UART now has a Configure procedure instead of Enable.

I2C addresses should include the R/W bit

The RP.I2C driver was expecting 7-bit I2C addresses to not include the R/W bit in the LSB. This was inconsistent with the other HAL.I2C implementations and would result in incorrect I2C addressing. Now, 7-bit I2C addresses should be represented as a UInt8 with the LSB set to 0. If this breaks your code, shift your I2C address left by one bit.

Bugs fixed

Improper use of the Pack clause

The Pack clause was used to enforce the memory layout of some records.

It is important to realize that pragma Pack must not be used to specify the exact representation of a data type, but to help the compiler to improve the efficiency of the generated code. Source

The Pack clause has been replaced with Component_Size and Size clauses where necessary. Thanks to @onox for pointing this out!

Use of access PIO_Device as a type discriminant

Projects depending on pico_bsp failed gnatprove in SPARK mode as the Pico.Audio_I2S package was using not null access PIO_Device as a discriminant. PIO_Device is now tagged and Pico.Audio_I2S uses not null access PIO_Device'Class, which is valid under SPARK. gnatprove still throws many warnings about side effects in the rp2040_hal drivers, but no fatal errors.

RP.ADC.Read_Microvolts was rounding incorrectly

Read_Microvolts was using Integer arithmetic to calculate VREF / Analog_Value'Last, which does not divide evenly for common VREF values. When that value was multiplied by an ADC reading, Read_Microvolts would return lower than expected results. Read_Microvolts now uses floating point to multiply ADC counts before converting the return value to Integer.

UART Transmit and Receive did not respect Timeout

The UART driver has been modified to use RP.Timer to implement timeouts and monitor FIFO status, similar to RP.SPI and RP.I2C.

SPI Transmit was nonblocking

The SPI Transmit procedure would return immediately after the last byte was written to the FIFO, but before the FIFO became empty. This behavior breaks some drivers that depend on all bytes being clocked out before proceeding. A configuration flag for Blocking behavior has been added and defaults to True.