Repository navigation
rpi-hal 0.10.0
Added
- I2C constructors that take a frequency:
I2c::<BSC1>::init_with_frequencyandI2c::<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 withdivider_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: whetherset_baudwould 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, asrpi-loaderacknowledges a baud change at the old rate.mailbox::Mailbox::measured_clock_rate_hz(tag0x0003_0047,
"Get Clock Rate Measured"): the rate a clock is actually running at, as
the firmware measures it.clock_rate_hzreports 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.
Themailbox_propsexample 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
bcm2712chip
feature, AArch64 only. There is no generated PAC for the chip, so
pacis 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 samePinAPI as the other chips, so the
blinkexample builds unchanged), the SoC's always-on GPIO block
(gio_aon), which carries the ACT LED (new exampleblink_act), and
uarton RP1's UART0, the same GPIO14/15 pins andUart::initcall as
the other chips, souart_helloanduart_echobuild unchanged. On
this chipinitsets RP1's UART clock itself, to its 50 MHz crystal,
rather than relying on the firmware's choice;init_bluetoothand the
asynchalf are left out.Uart::set_baudnow 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 the0xC000_0000alias the
older chips need, so the translation is the identity there.sd
builds too, over the Pi 5'ssdio1SDHCI controller (pac::SDIO1)
with the same API;sd_read,sd_resident_fat_readandsd_fat_write
run unchanged. The card's power and I/O voltage are always-on GPIO
lines on this board, soSd::initpower-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, soinit
takes but doesn't usemailboxthere. No DMA or async variants, and
sd::Error::Dmadoesn't exist underbcm2712.i2cbuilds too, as a
new driver for RP1's I2C controllers (Synopsys DesignWare), with
pac::BSC1naming I2C1 on GPIO2/3 andpac::BSC0I2C0 on GPIO0/1 so
header-bus code ports across; it does real repeated starts between a
transaction's operations, andi2c_sh1106_oledruns unchanged. The
AArch64 MMU maps the chip's peripherals above 4 GiB. The rest of the
crate iscfg'd out on this chip until each driver is checked against
it.multicore,fault-report,vchiq/mmalandv3dare rejected
with acompile_error!. The card needspciex4_reset=0in
config.txtto reach RP1.
Deprecated
I2c::<BSC1>::init,I2c::<BSC0>::initandI2c::<BSC0>::init_id,
which take a rawDIV.CDIV, in favour of theinit*_with_frequency
constructors. A raw divider only means what its caller thinks at one
core clock: the reset default0x05dc, 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_forstays, for working
out the rate a divider produces.
Fixed
-
sd_fat_read,sd_fat_writeandsd_resident_fat_readdidn't build
for the Pi 4. They took the controller asperipherals.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_writeseeds 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_frameare emitted for
aarch64-unknown-none-softfloat, andlinker64.lddidn't place them,
so the linker put them at the load address ahead of.text._start
moved to0x80800, and the firmware, which jumps to the load address,
started executing.eh_frame_hdrdata.linker64.ldnow discards both
sections; every profile ispanic = "abort", so nothing reads them. -
A nested critical section hung with the
multicorefeature. The
critical-sectioncrate allows nesting, and code nests without meaning
to — a log call inside acritical_section::withis one. With
multicoreon,acquirealso took a cross-core spinlock that was a
plain flag, which couldn't tell the core holding it from another core
asking, so an inneracquirespun 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
releasefrees it. New examplemulticore_critical_sectionchecks
nesting and that two cores still exclude each other. Builds without
multicoreare unchanged.