Skip to content

rpi-hal 0.10.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 22:54

Added

  • I2C constructors that take a frequency:
    I2c::<BSC1>::init_with_frequency and I2c::<BSC0>::init_with_frequency
    / init_id_with_frequency, each (gpio, bsc, frequency_hz, &mut mailbox, timer) -> Result<Self, mailbox::Error>. They ask the firmware
    for the core clock and compute the divider with divider_for, so SCL
    is the rate asked for (or the nearest below it) on any board and any
    config.txt. They exist on the Pi 5 too (all but the camera-bus one),
    so I2C code written against them builds for every chip. Every I2C
    example uses them now.
  • uart::Uart::supports_baud: whether set_baud would accept a
    rate, without touching the hardware, computed against the chip's own
    UART clock. For a protocol that agrees to a rate before switching to
    it, as rpi-loader acknowledges a baud change at the old rate.
  • mailbox::Mailbox::measured_clock_rate_hz (tag 0x0003_0047,
    "Get Clock Rate Measured"): the rate a clock is actually running at, as
    the firmware measures it. clock_rate_hz reports the rate the firmware
    has set, which can differ when the firmware moves a clock on its own,
    so its documentation no longer calls that the "real, current" rate.
    The mailbox_props example prints both for the ARM clock. On a Pi 2B
    they disagree from boot, 600 MHz set and 900 measured, and
    set_clock_rate_hz's documentation now says so: it claimed an unasked
    ARM clock stays at its floor, when it runs at full speed for a while
    and drops to the floor later.
  • Preliminary BCM2712 (Pi 5) support, behind a new bcm2712 chip
    feature, AArch64 only. There is no generated PAC for the chip, so
    pac is a small hand-written module of the same shape. What builds:
    the System Timer (timer), the 40-pin header's GPIO0-27 on the RP1
    south bridge (gpio, the same Pin API as the other chips, so the
    blink example builds unchanged), the SoC's always-on GPIO block
    (gio_aon), which carries the ACT LED (new example blink_act), and
    uart on RP1's UART0, the same GPIO14/15 pins and Uart::init call as
    the other chips, so uart_hello and uart_echo build unchanged. On
    this chip init sets RP1's UART clock itself, to its 50 MHz crystal,
    rather than relying on the firmware's choice; init_bluetooth and the
    async half are left out. Uart::set_baud now computes its divisor
    from the chip's UART clock instead of a hardcoded 48 MHz. mailbox
    builds too, at the BCM2712's address. Its firmware takes plain
    physical buffer addresses rather than the 0xC000_0000 alias the
    older chips need, so the translation is the identity there. sd
    builds too, over the Pi 5's sdio1 SDHCI controller (pac::SDIO1)
    with the same API; sd_read, sd_resident_fat_read and sd_fat_write
    run unchanged. The card's power and I/O voltage are always-on GPIO
    lines on this board, so Sd::init power-cycles the card through them
    into 3.3 V signalling rather than inheriting whatever mode the
    bootloader left it in. The base clock is a fixed 200 MHz, so init
    takes but doesn't use mailbox there. No DMA or async variants, and
    sd::Error::Dma doesn't exist under bcm2712. i2c builds too, as a
    new driver for RP1's I2C controllers (Synopsys DesignWare), with
    pac::BSC1 naming I2C1 on GPIO2/3 and pac::BSC0 I2C0 on GPIO0/1 so
    header-bus code ports across; it does real repeated starts between a
    transaction's operations, and i2c_sh1106_oled runs unchanged. The
    AArch64 MMU maps the chip's peripherals above 4 GiB. The rest of the
    crate is cfg'd out on this chip until each driver is checked against
    it. multicore, fault-report, vchiq/mmal and v3d are rejected
    with a compile_error!. The card needs pciex4_reset=0 in
    config.txt to reach RP1.

Deprecated

  • I2c::<BSC1>::init, I2c::<BSC0>::init and I2c::<BSC0>::init_id,
    which take a raw DIV.CDIV, in favour of the init*_with_frequency
    constructors. A raw divider only means what its caller thinks at one
    core clock: the reset default 0x05dc, documented as 100 kHz, is
    166 kHz on a board whose core runs at 250 MHz, and the Pi 5's
    controller has no divider at all. i2c::divider_for stays, for working
    out the rate a divider produces.

Fixed

  • sd_fat_read, sd_fat_write and sd_resident_fat_read didn't build
    for the Pi 4.
    They took the controller as peripherals.EMMC, which
    is the card's controller only on the Pi 2/3. They use
    Sd::steal_emmc() now, which names the right one on every chip, and
    sd_fat_write seeds its test value from the System Timer instead of
    the Pi 2/3-only hardware RNG.

  • AArch64 images started with unwind tables instead of code. With
    the current nightly, .eh_frame_hdr/.eh_frame are emitted for
    aarch64-unknown-none-softfloat, and linker64.ld didn't place them,
    so the linker put them at the load address ahead of .text. _start
    moved to 0x80800, and the firmware, which jumps to the load address,
    started executing .eh_frame_hdr data. linker64.ld now discards both
    sections; every profile is panic = "abort", so nothing reads them.

  • A nested critical section hung with the multicore feature. The
    critical-section crate allows nesting, and code nests without meaning
    to — a log call inside a critical_section::with is one. With
    multicore on, acquire also took a cross-core spinlock that was a
    plain flag, which couldn't tell the core holding it from another core
    asking, so an inner acquire spun forever waiting for its own core.
    The lock now records its owner (cpu::core_id) and a depth: the owning
    core goes a level deeper, other cores wait, and only the outermost
    release frees it. New example multicore_critical_section checks
    nesting and that two cores still exclude each other. Builds without
    multicore are unchanged.