1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
//! Hardware abstraction layer for bare-metal Raspberry Pi.
//!
//! Built around the BCM2836/BCM2837 (Pi 2, Pi 3), with preliminary
//! support for the BCM2711 (Pi 4), the BCM2835 (Pi 1, Pi Zero) and the
//! BCM2712 (Pi 5) — see the crate's README for what is verified on each.
//! Exactly one of the `bcm2837`/`bcm2711`/`bcm2835`/`bcm2712` features
//! selects the chip; none is a default, since there is no sensible default
//! target chip.
// docs.rs builds with `--cfg docsrs` (see `[package.metadata.docs.rs]` in
// Cargo.toml), which turns on rustdoc labelling every feature-gated item
// with the feature that provides it -- without it a reader sees modules
// like `gpio::asynch` with no indication that a feature is needed to get
// them. Gated on the cfg rather than unconditional because it's a
// nightly-only rustdoc feature.
// The BCM2712 (Pi 5) builds only a handful of the modules below, and the
// `not(feature = "bcm2712")` on the rest is that list. Each one left out
// drives a peripheral the BCM2712 does not have where the driver expects
// it: most of the I/O moved onto the RP1 south bridge as different IP
// (RP1's GPIO, for one, shares nothing with the BCM283x block), and what
// stayed on the SoC moved address. What remains is CPU state (caches, MMU,
// FPU, PMU, exception vectors), the System Timer, and the two GPIO drivers
// written for this chip. A module rejoins once it has been checked against
// the BCM2712's own block, not before: one quietly built against the wrong
// register map would compile and then hang on its first access.
/// Audio out through the VideoCore firmware's `ril.audio_render` MMAL
/// component — HDMI, or the analog jack.
/// Blocking driver for the auxiliary SPI controllers SPI1 and SPI2.
/// HCI bring-up for the on-board BCM43438 Bluetooth controller (Pi 3):
/// H4 transport, `.hcd` patchram firmware load, and local
/// version/address readback.
/// Identity of the core executing this code — see the module's own doc
/// comment for why this is not part of `multicore`.
/// Blocking driver for the DMA controller.
// Installs `__unhandled_exception` rather than offering an API, so there
// is nothing here to make public -- see the module's own documentation.
/// Enabling the hardware floating-point / SIMD unit (VFP + NEON).
/// Per-core ARM generic (architected) timer: monotonic counter, blocking
/// delays, and interrupt-driven deadlines.
///
/// Not built for ARMv6 (BCM2835): the generic timer is an ARMv7-A
/// extension, and the per-core control and routing registers this driver
/// programs live in an ARM-local peripheral block the BCM2835 does not
/// have. [`timer`] — the BCM System Timer, a peripheral rather than CPU
/// state — is the monotonic clock there.
///
/// Not built for BCM2712 yet either: the counter itself is CPU state, but
/// the per-core control registers this driver programs sit in the
/// BCM2836's ARM-local block, which the BCM2712 does not have.
/// The BCM2712's always-on GPIO block, which carries the Pi 5's ACT LED.
/// Typestated GPIO pin wrapper with `embedded-hal` `digital` trait
/// implementations.
/// Typestated GPIO pin wrapper with `embedded-hal` `digital` trait
/// implementations, over the header pins on the Pi 5's RP1.
/// Transport-independent HID report descriptor parser, shared by the USB
/// and Bluetooth HID hosts — see [`hid_report::ReportDescriptor`].
/// Blocking driver for I2C1 (BSC1).
/// Blocking driver for the header's I2C buses, on the Pi 5's RP1.
/// CPU-level IRQ enable/disable and the exception vector table.
/// Safe wrapper around the BCM2836/2837 legacy interrupt controller.
///
/// Not built under `bcm2711`: BCM2711 wires a different set of
/// peripherals through the surviving legacy IC block (its PAC's bit
/// names for the shared pending/enable registers genuinely differ, not
/// just cosmetically), and it's superseded there by GIC-400 anyway --
/// a real, separate driver this crate doesn't have yet. No interrupt
/// controller is available under `bcm2711` until that lands, so nothing
/// interrupt-driven works there either.
/// Blocking driver for the VideoCore mailbox property interface.
/// Where the loaded image ends and free RAM begins — see
/// [`mem::heap_region`], which is how a program sizes a heap without
/// hardcoding a board's memory split.
///
/// Needs the `rt` feature, since the boundary it reports is the one this
/// crate's linker script places. A program supplying its own script owns
/// that layout instead.
/// Blocking driver for the mini UART (UART1).
/// Client for the VideoCore firmware's MMAL multimedia framework, over
/// [`vchiq`] — components, ports, parameters, and buffer exchange.
/// Identity-mapped MMU bring-up, plus the one thing a driver may need to
/// change about the map afterwards: taking a region of RAM out of the
/// caches ([`mmu::set_uncached`]), for memory a bus master writes
/// concurrently with this core.
/// Bringing up secondary cores (1-3) — see the module's own doc
/// comment for the wake-up handoff this builds on.
///
/// Not built for ARMv6 (BCM2835): that chip has one core, and no
/// ARM-local mailbox registers for a second one to be woken through. The
/// `multicore` feature is rejected outright there rather than quietly
/// producing a build without this module — see the `compile_error!`
/// below.
// A consumer who asked for `multicore` on a uniprocessor chip asked for
// something that cannot be delivered, and the failure to be loud about is
// the silent one: without this, the feature would simply compile away and
// the first sign would be `rpi_hal::multicore` not resolving.
compile_error!;
// The same loud failure for the features whose subsystems the BCM2712 does
// not have yet. Each is a feature a consumer opts into by name, so it is
// asking for something specific, and quietly compiling it away would leave
// them a missing module or a link error instead of a reason.
compile_error!;
compile_error!;
compile_error!;
/// Reference I2C driver for the OV5647 (Raspberry Pi Camera v1) image
/// sensor — a third-party device (paired with [`unicam`]), not a SoC
/// peripheral.
/// Peripheral access for the BCM2712 (Pi 5): the hand-written stand-in for
/// the generated PAC the other chips re-export under this name.
/// Blocking bring-up for the PCM / I2S peripheral (digital audio out to an
/// external I2S DAC).
/// The PMU cycle counter — a cheap per-core CPU-cycle clock for profiling
/// work too short for the System Timer to measure without disturbing it.
///
/// Not built for ARMv6 (BCM2835): the ARM1176 has performance counters,
/// but behind entirely different CP15 registers from the ARMv7-A PMU this
/// driver programs. [`timer`] is the clock available there.
/// Board reboot and shutdown via the Power Management (PM) block.
/// Blocking driver for the PWM controller.
/// Blocking driver for the hardware random number generator.
/// Blocking driver for the on-board SD card slot (Arasan EMMC host
/// controller, or the SDHCI that replaced it on the Pi 4 and Pi 5).
/// Blocking driver for the SD card slot over the *other* host
/// controller, SDHOST — the one that leaves the Arasan controller free
/// for [`sdio`], so a board can drive its card and its wireless chip at
/// the same time.
///
/// Not built for BCM2711: a Pi 4 drives its card from EMMC2, which is a
/// separate block again, and GPIO48-53 there are the Ethernet PHY's
/// RGMII interface rather than the card slot — so routing them here
/// would be actively wrong rather than merely useless.
/// Blocking SDIO driver for the on-board BCM43438 wireless chip (Wi-Fi
/// side), via the same Arasan EMMC host controller.
/// Blocking driver for SPI0.
/// Extent of the main stack and how much of it is left — see
/// [`stack::headroom`].
///
/// Needs the `rt` feature, since the region it reports on is the one
/// this crate's linker script reserves and its boot code points `sp`
/// at. A program supplying its own boot code and linker script owns
/// that layout instead.
/// BCM System Timer driver: free-running microsecond counter and delays.
/// Driver for the DSI touchscreen's touch input (the firmware-mediated
/// shared touch buffer, not I2C).
/// Blocking driver for UART0 (PL011) — on the Pi 5, RP1's UART0, on the
/// same GPIO14/15 header pins.
/// Blocking driver for the Unicam CSI-2 camera receiver.
/// USB host support for the built-in DWC2 OTG controller.
/// Bring-up for the V3D 3D pipeline (VideoCore IV's QPU shader cores).
/// Pi 3 (BCM2836/BCM2837) only.
/// VCHIQ: the shared-memory, doorbell-signalled message transport to the
/// VideoCore firmware — everything the simple request/response
/// [`mailbox`] can't carry.
/// Hardware H.264 video decode, driven through the VideoCore firmware's
/// `ril.video_decode` MMAL component.
/// Blocking driver for the PM block's watchdog timer.
/// Host control protocol (SDPCM/CDC) for the on-board BCM43430 Wi-Fi
/// chip, on top of `sdio`.
/// Re-export of the underlying peripheral access crate, for direct
/// register access alongside this crate's higher-level wrappers.
/// Whichever of `bcm2837`/`bcm2711`/`bcm2835` is enabled (see
/// `Cargo.toml`) -- with more than one on, the precedence is
/// `bcm2712` > `bcm2711` > `bcm2837` > `bcm2835`, newest chip first, and
/// the same order every other chip branch in this crate follows. The
/// `bcm2712` arm is the `pac` module above rather than a re-export, since
/// that chip has no generated PAC.
pub use bcm2711_lpa as pac;
pub use bcm2835_lpa as pac;
pub use bcm2837_lpa as pac;
// With neither feature on there is no `pac` at all, and every module that
// reaches for a register fails to resolve it -- 18 errors naming
// `crate::pac` and none of them saying a chip has to be chosen. This is
// the third arm of the re-export above, and it puts that sentence in
// front of them: expansion runs before name resolution, so this is the
// first error printed, and rustc gives up early enough afterwards that
// the tail shrinks to two (the unresolved `crate::pac`, and an
// `i2c.rs`/`init` duplicate-definition that only looks like one because
// the two impls' distinguishing types come from `pac`). Not silenced
// entirely -- that would mean stubbing out a fake `pac`, a worse trade
// than a short cascade under a clear headline.
compile_error!;
// The Pi 5's boot firmware starts 64-bit kernels only, so a 32-bit build
// would produce an image nothing can run -- and `pac`'s addresses, all
// above 4 GiB, would not even fit a pointer.
compile_error!;
/// Halts the calling core forever, parking it in a low-power
/// wait-for-event loop.
///
/// Useful as the terminal state of a bare-metal `kmain` or as the tail
/// of a `#[panic_handler]`, where there is nothing left to do and no OS
/// to return to.
!