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
//! The bring-up an application does before it is an application, for
//! bare-metal Raspberry Pi boards built on `rpi-hal`.
//!
//! `rpi-hal` stops at the peripheral: it hands out a `Uart`, a `Mailbox`,
//! an `Sd`. What every board then does with them is the same program
//! written again — a console the whole image can print to, a heap sized
//! from what the firmware reports, a card mounted and a settings file read
//! off it, a site served out of RAM, a clock that something has to set.
//! This crate is that program, once.
//!
//! # Everything is opt-in, and everything is replaceable
//!
//! Each capability is its own feature and its own module, and none of
//! them are on by default: a board states what it is, and pays for
//! nothing else. Where a piece has a plausible second implementation —
//! the time source above all, which may be the network on one board and a
//! DS3231 on the next — what this crate owns is the *sink* the rest of the
//! image reads through, and filling it is the application's to choose.
//!
//! The same principle draws the line at the executor. An
//! `#[embassy_executor::task]` cannot be generic, so this crate never
//! declares one; it exposes `async fn`s and the application wraps them in
//! tasks with its own concrete types. Routing, the global allocator and
//! the panic handler stay with the application for the same reason — they
//! are single, program-wide choices that a library taking them away
//! cannot give back.
//!
//! # What an application must provide
//!
//! - **`rpi-hal`'s `rt` feature**, which supplies the boot sequence,
//! the vector table and the `critical-section` implementation.
//! - **`rpi-hal`'s `mmu` feature** (on by default) for anything using
//! atomics, which includes every `embassy` executor.
//! - **A `#[global_allocator]` and a `#[panic_handler]`.** A program may
//! have only one of each, so neither can come from a library.
extern crate alloc;
// The splash encoder and the build-info capture run in a board's
// `build.rs`, on the host, and read files and run `git`.
extern crate std;
/// Password login for a board's web interface — see the module's own
/// documentation for what it protects against and what it does not.
/// The wall clock — see the module's own documentation for why it is a
/// sink with no source of its own, and why it reads `None` until set.
/// Reading a board's settings file — see the module's own documentation
/// for why the semantic checks run after parsing rather than inside it.
/// The console every module logs to — see the module's own documentation
/// for why its sink is a trait object and its clock is passed in.
///
/// The macro that writes to it, [`logln!`], is at the crate root: an
/// exported `macro_rules!` lands there whatever file it is written in.
/// Hardware entropy, and the `getrandom` backend the crypto stack needs —
/// see the module's own documentation for what enabling it decides for
/// the whole program.
/// The global heap — see the module's own documentation for why it
/// declares the `#[global_allocator]` and what that decides for the rest
/// of the program.
/// A minimal HTTPS client — see the module's own documentation for why it
/// is one request per connection, and why the body comes back whatever the
/// status.
/// An mDNS responder for one name — see the module's own documentation
/// for the half of the multicast plumbing the board still has to do.
/// Writing Prometheus's text exposition format — see the module's own
/// documentation for decimals without a float formatter, and why a label
/// value is only ever written escaped.
/// Getting a board onto the network, whichever way it can — see the
/// module's own documentation for why "is Ethernet available" is two
/// questions and both are deadlines.
/// Outbound notifications and the channels that deliver them — see the
/// module's own documentation for what stays the board's.
/// Over-the-air updates: the upload route and the reboot after it — see
/// the module's own documentation for the one response shape every board
/// answers with.
/// The board's web assets, read off the card into RAM — see the module's
/// own documentation for why the site lives on the card at all.
/// Setting the clock from an NTP server — see the module's own
/// documentation for what its reply checks do and do not protect against.
/// A boot logo baked into the kernel image — see the module's own
/// documentation for why it is run-length-encoded RGB565, and for the
/// encoder a board's `build.rs` calls.
/// Mounting the card's FAT volume — see the module's own documentation
/// for what it costs in RAM and what time the files it writes carry.
/// TLS client connections with real certificate verification — see the
/// module's own documentation for the three things a Pi has to supply,
/// one of them an unaudited crypto provider.
/// Serving HTTP with `picoserve` — see the module's own documentation for
/// why this is pieces of a router rather than a server task.