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
// Copyright 2026 Ethan Wu
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
//! Consortium HAL for STM32MP2 family devices.
//!
//! Peripherals are owned, not addressed. [`init`] hands out the chip's
//! singletons once as a [`Peripherals`] struct, and each driver's constructor
//! consumes the one it drives:
//!
//! ```ignore
//! let p = consortium_hal_stm32mp2::init();
//! let i2c = consortium_hal_stm32mp2::i2c::I2c::new(p.I2C1, 64_000_000, 400_000);
//! ```
//!
//! Because the base address and NVIC line travel with the singleton, no driver
//! takes an MMIO pointer and no constructor is `unsafe`. Bring-up that runs
//! outside [`init`] — a second-stage loader, a test harness — can still reach a
//! peripheral through `peripherals::<NAME>::steal()`, which carries the
//! exclusivity obligation the safe path discharges.
//!
//! # Layering
//!
//! ```text
//! consortium-hal Peri, PeripheralType, peripherals!, narrow traits
//! └── consortium-hal-stm32mp2 (this crate) drivers + generated singletons
//! └── consortium-pac-stm32mp2 register blocks, Interrupt, vector table
//! ```
//!
//! Both are re-exported ([`hal`], [`pac`]), so a firmware crate needs one dependency.
//! [`interrupts`], [`Interrupt`], and — behind `rt` — the `interrupt` attribute macro
//! come straight from the PAC.
//!
//! # Drivers
//!
//! Each is behind a feature, all on by default: `adc`, `can`, `dma`, `gpio`,
//! `i2c`, `i3c`, `lptim`, `spi`, `timer`, `timer_driver`, `uart`, `watchdog`.
//!
//! `timer_driver` (`time-driver-gp-tim`) is the Embassy time driver over TIM2;
//! `consortium-cfg` emits its bring-up into the generated `init()` unless
//! `[profile] time_driver = false`.
//!
//! # Chip selection
//!
//! `stm32mp21x`, `stm32mp23x`, or `stm32mp25x` — **exactly one**.
//!
//! `stm32mp23x` and `stm32mp25x` share one die, memory map and interrupt numbering
//! (RM0457), so both forward to the PAC's `stm32mp257` chip. Each has its own
//! singleton map: MP23 lacks the instances its datasheet (DS14634) rules out, such
//! as I2C3–6, FDCAN3, TIM20, LPDMA and IPCC2. `stm32mp21x` has its own map. Enabling
//! several is a duplicate-definition error.
//!
//! Default is `stm32mp25x`. **A dependent selecting another chip must set
//! `default-features = false`**, or `stm32mp25x` comes along too and the PAC's
//! `Interrupt` enum becomes ambiguous. The doorbell and UART-transport crates all do
//! this.
//!
//! # Interrupts are the application's
//!
//! This crate installs no `#[interrupt]` handlers. The application owns the vector
//! table and forwards each vector into the driver's entry point, parameterized with
//! the same singleton the driver consumed:
//!
//! ```rust,ignore
//! #[interrupt]
//! fn USART2() {
//! consortium_hal_stm32mp2::uart::on_buffered_interrupt::<peripherals::USART2>();
//! }
//! ```
//!
//! Enable `rt` so the `#[interrupt]` macro and PAC vector table are available there.
//! The same applies to the doorbell crates: HSEM and IPCC RX vectors are forwarded by
//! application code, not installed here.
//!
//! # Generated code
//!
//! `src/peripherals/<chip>.rs` is generated by `scripts/pac/gen_peripherals.py` from
//! the same `consortium-data` chip dumps that feed `gen_interrupts.py`. It declares the
//! singletons and invokes each driver's `impl_<driver>!` macro with that instance's
//! base and NVIC line — so the generated file is **data only** and the driver module
//! owns the logic. Re-run the generator after changing a chip dump rather than editing
//! it.
//!
//! # Secure aliases
//!
//! The singletons carry only the **non-secure** alias of each peripheral window. That
//! is why `consortium-cfg` rejects `[peripheral.*]` entries with `secure = true`: there
//! is no singleton to hand out for the secure view.
extern crate std;
pub use consortium_hal as hal;
/// Ownership handle and marker trait for peripheral singletons, re-exported so
/// drivers in other crates can name them without depending on Embassy directly.
pub use ;
pub use consortium_pac_stm32mp2 as pac;
// Peripheral singletons and their driver bindings, generated from the chip
// databases by `scripts/pac/gen_peripherals.py`. Chip features are mutually
// exclusive; enabling several is a duplicate-definition error, matching the PAC.
// `stm32mp23x` shares the PAC's STM32MP257 interrupt table but has its own map.
pub use ;
/// Take the chip's peripheral singletons.
///
/// # Panics
///
/// Panics if called more than once — the singletons are exactly that, and
/// handing them out twice would let two drivers claim the same registers.
/// Interrupt lines for the selected chip, re-exported from the PAC for direct
/// HAL consumers.
pub use interrupts;
pub use Interrupt;
/// The `#[interrupt]` attribute macro, available when the `rt` feature is on.
pub use interrupt;