aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoël Schulz-Ansres <[email protected]>2024-05-02 13:36:44 +0200
committerJoël Schulz-Ansres <[email protected]>2024-05-02 13:43:42 +0200
commit9fe50a7639a046bafe9d2003847476cbfd61db1d (patch)
tree46f05c008a2de6e4b23c080868cb0ccc891dcf19
parent45a2abc392df91ce6963ac0956f48f22bfa1489b (diff)
Add stm32 dsihost driver
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/build.rs29
-rw-r--r--embassy-stm32/src/dsihost.rs363
-rw-r--r--embassy-stm32/src/lib.rs4
-rw-r--r--embassy-stm32/src/ltdc.rs134
-rw-r--r--embassy-stm32/src/rcc/f247.rs5
-rw-r--r--embassy-stm32/src/rcc/h.rs3
-rw-r--r--embassy-stm32/src/rcc/l.rs3
-rw-r--r--embassy-stm32/src/rcc/u5.rs3
9 files changed, 543 insertions, 2 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index a50da1a9e..a7137d132 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -89,7 +89,6 @@ volatile-register = { version = "0.2.1" }
89bitflags = "2.4.2" 89bitflags = "2.4.2"
90 90
91 91
92
93[dev-dependencies] 92[dev-dependencies]
94critical-section = { version = "1.1", features = ["std"] } 93critical-section = { version = "1.1", features = ["std"] }
95 94
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index ba118f338..dbc8f9153 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -836,6 +836,35 @@ fn main() {
836 (("dcmi", "HSYNC"), quote!(crate::dcmi::HSyncPin)), 836 (("dcmi", "HSYNC"), quote!(crate::dcmi::HSyncPin)),
837 (("dcmi", "VSYNC"), quote!(crate::dcmi::VSyncPin)), 837 (("dcmi", "VSYNC"), quote!(crate::dcmi::VSyncPin)),
838 (("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)), 838 (("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)),
839 (("dsihost", "TE"), quote!(crate::dsihost::TePin)),
840 (("ltdc", "CLK"), quote!(crate::ltdc::ClkPin)),
841 (("ltdc", "HSYNC"), quote!(crate::ltdc::HsyncPin)),
842 (("ltdc", "VSYNC"), quote!(crate::ltdc::VsyncPin)),
843 (("ltdc", "DE"), quote!(crate::ltdc::DePin)),
844 (("ltdc", "R0"), quote!(crate::ltdc::R0Pin)),
845 (("ltdc", "R1"), quote!(crate::ltdc::R1Pin)),
846 (("ltdc", "R2"), quote!(crate::ltdc::R2Pin)),
847 (("ltdc", "R3"), quote!(crate::ltdc::R3Pin)),
848 (("ltdc", "R4"), quote!(crate::ltdc::R4Pin)),
849 (("ltdc", "R5"), quote!(crate::ltdc::R5Pin)),
850 (("ltdc", "R6"), quote!(crate::ltdc::R6Pin)),
851 (("ltdc", "R7"), quote!(crate::ltdc::R7Pin)),
852 (("ltdc", "G0"), quote!(crate::ltdc::G0Pin)),
853 (("ltdc", "G1"), quote!(crate::ltdc::G1Pin)),
854 (("ltdc", "G2"), quote!(crate::ltdc::G2Pin)),
855 (("ltdc", "G3"), quote!(crate::ltdc::G3Pin)),
856 (("ltdc", "G4"), quote!(crate::ltdc::G4Pin)),
857 (("ltdc", "G5"), quote!(crate::ltdc::G5Pin)),
858 (("ltdc", "G6"), quote!(crate::ltdc::G6Pin)),
859 (("ltdc", "G7"), quote!(crate::ltdc::G7Pin)),
860 (("ltdc", "B0"), quote!(crate::ltdc::B0Pin)),
861 (("ltdc", "B1"), quote!(crate::ltdc::B1Pin)),
862 (("ltdc", "B2"), quote!(crate::ltdc::B2Pin)),
863 (("ltdc", "B3"), quote!(crate::ltdc::B3Pin)),
864 (("ltdc", "B4"), quote!(crate::ltdc::B4Pin)),
865 (("ltdc", "B5"), quote!(crate::ltdc::B5Pin)),
866 (("ltdc", "B6"), quote!(crate::ltdc::B6Pin)),
867 (("ltdc", "B7"), quote!(crate::ltdc::B7Pin)),
839 (("usb", "DP"), quote!(crate::usb::DpPin)), 868 (("usb", "DP"), quote!(crate::usb::DpPin)),
840 (("usb", "DM"), quote!(crate::usb::DmPin)), 869 (("usb", "DM"), quote!(crate::usb::DmPin)),
841 (("otg", "DP"), quote!(crate::usb::DpPin)), 870 (("otg", "DP"), quote!(crate::usb::DpPin)),
diff --git a/embassy-stm32/src/dsihost.rs b/embassy-stm32/src/dsihost.rs
new file mode 100644
index 000000000..c55fa8411
--- /dev/null
+++ b/embassy-stm32/src/dsihost.rs
@@ -0,0 +1,363 @@
1//! DSI HOST
2
3use crate::rcc::RccPeripheral;
4use core::marker::PhantomData;
5use embassy_hal_internal::{into_ref, PeripheralRef};
6
7//use crate::gpio::{AnyPin, SealedPin};
8use crate::gpio::{AFType, AnyPin, Pull, Speed};
9use crate::{peripherals, Peripheral};
10
11/// Performs a busy-wait delay for a specified number of microseconds.
12pub fn blocking_delay_ms(ms: u32) {
13 #[cfg(time)]
14 embassy_time::block_for(embassy_time::Duration::from_millis(ms));
15 #[cfg(not(time))]
16 cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 1_000 * ms);
17}
18
19/// PacketTypes extracted from CubeMX
20#[repr(u8)]
21#[allow(dead_code)]
22pub enum PacketType {
23 /// DCS short write, no parameters
24 DcsShortPktWriteP0,
25 /// DCS short write, one parameter
26 DcsShortPktWriteP1,
27 /// Generic short write, no parameters
28 GenShortPktWriteP0,
29 /// Generic short write, one parameter
30 GenShortPktWriteP1,
31 /// Generic short write, two parameters
32 GenShortPktWriteP2,
33 /// DCS long write
34 DcsLongPktWrite,
35 /// Generic long write
36 GenLongPktWrite,
37 /// DCS short read
38 DcsShortPktRead(u8),
39 /// Generic short read, no parameters
40 GenShortPktReadP0,
41 /// Generic short read, one parameter
42 GenShortPktReadP1(u8),
43 /// Generic short read, two parameters
44 GenShortPktReadP2(u8, u8),
45 /// Used to set the maximum return packet size for reading data
46 MaxReturnPktSize,
47}
48
49impl From<PacketType> for u8 {
50 fn from(packet_type: PacketType) -> u8 {
51 match packet_type {
52 PacketType::DcsShortPktWriteP0 => 0x05,
53 PacketType::DcsShortPktWriteP1 => 0x15,
54 PacketType::GenShortPktWriteP0 => 0x03,
55 PacketType::GenShortPktWriteP1 => 0x13,
56 PacketType::GenShortPktWriteP2 => 0x23,
57 PacketType::DcsLongPktWrite => 0x39,
58 PacketType::GenLongPktWrite => 0x29,
59 PacketType::DcsShortPktRead(_) => 0x06,
60 PacketType::GenShortPktReadP0 => 0x04,
61 PacketType::GenShortPktReadP1(_) => 0x14,
62 PacketType::GenShortPktReadP2(_, _) => 0x24,
63 PacketType::MaxReturnPktSize => 0x37,
64 }
65 }
66}
67
68/// DSIHOST driver.
69pub struct DsiHost<'d, T: Instance> {
70 _peri: PhantomData<&'d mut T>,
71 _te: PeripheralRef<'d, AnyPin>,
72}
73
74impl<'d, T: Instance> DsiHost<'d, T> {
75 /// Note: Full-Duplex modes are not supported at this time
76 pub fn new(_peri: impl Peripheral<P = T> + 'd, te: impl Peripheral<P = impl TePin<T>> + 'd) -> Self {
77 into_ref!(te);
78
79 T::enable_and_reset();
80
81 // Set Tearing Enable pin according to CubeMx example
82 te.set_as_af_pull(te.af_num(), AFType::OutputPushPull, Pull::None);
83 te.set_speed(Speed::Low);
84 /*
85 T::regs().wcr().modify(|w| {
86 w.set_dsien(true);
87 });
88 */
89 Self {
90 _peri: PhantomData,
91 _te: te.map_into(),
92 }
93 }
94
95 /// Get the DSIHOST hardware version. Found in the reference manual for comparison.
96 pub fn get_version(&self) -> u32 {
97 T::regs().vr().read().version()
98 }
99
100 /// Set the enable bit in the control register and assert that it has been enabled
101 pub fn enable(&mut self) {
102 T::regs().cr().modify(|w| w.set_en(true));
103 assert!(T::regs().cr().read().en())
104 }
105
106 /// Unset the enable bit in the control register and assert that it has been disabled
107 pub fn disable(&mut self) {
108 T::regs().cr().modify(|w| w.set_en(false));
109 assert!(!T::regs().cr().read().en())
110 }
111
112 /// Set the DSI enable bit in the wrapper control register and assert that it has been enabled
113 pub fn enable_wrapper_dsi(&mut self) {
114 T::regs().wcr().modify(|w| w.set_dsien(true));
115 assert!(T::regs().wcr().read().dsien())
116 }
117
118 /// Unset the DSI enable bit in the wrapper control register and assert that it has been disabled
119 pub fn disable_wrapper_dsi(&mut self) {
120 T::regs().wcr().modify(|w| w.set_dsien(false));
121 assert!(!T::regs().wcr().read().dsien())
122 }
123
124 /// DCS or Generic short/long write command
125 pub fn write_cmd(&mut self, channel_id: u8, params: &[u8]) {
126 if params.len() <= 2 {
127 self.short_write(channel_id, PacketType::DcsShortPktWriteP1, params[0], params[1])
128 } else {
129 self.long_write(
130 channel_id,
131 PacketType::DcsLongPktWrite, // FIXME: This might be a generic long packet, as well...
132 params,
133 )
134 }
135 }
136
137 fn short_write(&mut self, channel_id: u8, packet_type: PacketType, param1: u8, param2: u8) {
138 #[cfg(feature = "defmt")]
139 defmt::debug!("short_write: BEGIN wait for command fifo empty");
140
141 // Wait for Command FIFO empty
142 self.wait_command_fifo_empty().unwrap();
143 #[cfg(feature = "defmt")]
144 defmt::debug!("short_write: END wait for command fifo empty");
145
146 // Configure the packet to send a short DCS command with 0 or 1 parameters
147 // Update the DSI packet header with new information
148 self.config_packet_header(channel_id, packet_type, param1, param2);
149 }
150
151 fn config_packet_header(&mut self, channel_id: u8, packet_type: PacketType, param1: u8, param2: u8) {
152 T::regs().ghcr().write(|w| {
153 w.set_dt(packet_type.into());
154 w.set_vcid(channel_id);
155 w.set_wclsb(param1);
156 w.set_wcmsb(param2);
157 });
158 }
159
160 /// Write long DCS or long Generic command.
161 ///
162 /// `params` is expected to contain at least 3 elements. Use [`short_write`] for 2 or less.
163 fn long_write(&mut self, channel_id: u8, packet_type: PacketType, params: &[u8]) {
164 // Must be a long packet if we do the long write, obviously.
165 assert!(matches!(
166 packet_type,
167 PacketType::DcsLongPktWrite | PacketType::GenLongPktWrite
168 ));
169
170 // params needs to have at least 3 elements, otherwise short_write should be used
171 assert!(params.len() >= 3);
172
173 #[cfg(feature = "defmt")]
174 defmt::debug!("long_write: BEGIN wait for command fifo empty");
175
176 self.wait_command_fifo_empty().unwrap();
177
178 #[cfg(feature = "defmt")]
179 defmt::debug!("long_write: DONE wait for command fifo empty");
180
181 let dcs_code = params[params.len() - 1]; // FIXME: DCS Code stored in the last element. Should probably be a separate argument.
182 let data = &params[0..params.len() - 1]; // data is all elements except for the dcs_code
183
184 // Note: CubeMX example "NbParams" is always one LESS than params.len()
185 // DCS code (last element of params) must be on payload byte 1 and if we have only 2 more params,
186 // then they must go into data2 and data3
187 T::regs().gpdr().write(|w| {
188 // data[2] may or may not exist.
189 if let Some(x) = data.get(2) {
190 w.set_data4(*x);
191 }
192 // data[0] and [1] have to exist if long_write is called.
193 w.set_data3(data[1]);
194 w.set_data2(data[0]);
195 // DCS Code
196 w.set_data1(dcs_code);
197 });
198
199 // FIXME: This probably should return an error
200 self.wait_command_fifo_empty().unwrap();
201
202 // These steps are only necessary if more than 1x 4 bytes need to go into the FIFO
203 if data.len() >= 4 {
204 // Generate an iterator that iterates over chunks of exactly 4 bytes
205 let iter = data[3..data.len()].chunks_exact(4);
206 // Obtain remainder before consuming iter
207 let remainder = iter.remainder();
208
209 // Keep filling the buffer with remaining data
210 for param in iter {
211 T::regs().gpdr().write(|w| {
212 w.set_data4(param[3]);
213 w.set_data3(param[2]);
214 w.set_data2(param[1]);
215 w.set_data1(param[0]);
216 });
217
218 self.wait_command_fifo_empty().unwrap();
219 }
220
221 // If the remaining data was not devisible by 4 we get a remainder
222 if remainder.len() >= 1 {
223 T::regs().gpdr().write(|w| {
224 if let Some(x) = remainder.get(2) {
225 w.set_data3(*x);
226 }
227 if let Some(x) = remainder.get(1) {
228 w.set_data2(*x);
229 }
230 w.set_data1(remainder[0]);
231 });
232 self.wait_command_fifo_empty().unwrap();
233 }
234 }
235 // Configure the packet to send a long DCS command
236 T::regs().ghcr().write(|w| {
237 w.set_dt(packet_type.into());
238 w.set_vcid(channel_id);
239 w.set_wclsb((params.len() & 0x00FF) as u8);
240 w.set_wcmsb((params.len() & 0xFF00 >> 8) as u8);
241 });
242 }
243
244 pub fn read(
245 &mut self,
246 channel_id: u8,
247 packet_type: PacketType,
248 read_size: u16,
249 data: &mut [u8],
250 ) -> Result<(), Error> {
251 if data.len() != read_size as usize {
252 return Err(Error::InvalidReadSize);
253 }
254
255 // Set the maximum return packet size
256 self.short_write(
257 channel_id,
258 PacketType::MaxReturnPktSize,
259 (read_size & 0xFF) as u8,
260 ((read_size >> 8) & 0xFF) as u8,
261 );
262
263 // Set the packet header according to the packet_type
264 use PacketType::*;
265 match packet_type {
266 DcsShortPktRead(cmd) => self.config_packet_header(channel_id, packet_type, cmd, 0),
267 GenShortPktReadP0 => self.config_packet_header(channel_id, packet_type, 0, 0),
268 GenShortPktReadP1(param1) => self.config_packet_header(channel_id, packet_type, param1, 0),
269 GenShortPktReadP2(param1, param2) => self.config_packet_header(channel_id, packet_type, param1, param2),
270 _ => return Err(Error::InvalidPacketType),
271 }
272
273 // Obtain chunks of 32-bit so the entire FIFO data register can be read
274 for bytes in data.chunks_exact_mut(4) {
275 self.wait_payload_read_fifo_not_empty().unwrap();
276
277 // Only perform a single read on the entire register to avoid unintended side-effects
278 let gpdr = T::regs().gpdr().read();
279 bytes[0] = gpdr.data1();
280 bytes[1] = gpdr.data2();
281 bytes[2] = gpdr.data3();
282 bytes[3] = gpdr.data4();
283 }
284
285 // Collect the remaining chunks and read the corresponding number of bytes from the FIFO
286 let remainder = data.chunks_exact_mut(4).into_remainder();
287 if !remainder.is_empty() {
288 self.wait_payload_read_fifo_not_empty().unwrap();
289 // Only perform a single read on the entire register to avoid unintended side-effects
290 let gpdr = T::regs().gpdr().read();
291 if let Some(x) = remainder.get_mut(0) {
292 *x = gpdr.data1()
293 }
294 if let Some(x) = remainder.get_mut(1) {
295 *x = gpdr.data2()
296 }
297 if let Some(x) = remainder.get_mut(2) {
298 *x = gpdr.data3()
299 }
300 }
301
302 Ok(())
303 }
304 fn wait_command_fifo_empty(&self) -> Result<(), Error> {
305 for _ in 1..1000 {
306 // Wait for Command FIFO empty
307 if T::regs().gpsr().read().cmdfe() {
308 return Ok(());
309 }
310 blocking_delay_ms(1);
311 }
312 Err(Error::FifoTimeout)
313 }
314
315 fn wait_payload_read_fifo_not_empty(&self) -> Result<(), Error> {
316 for _ in 1..1000 {
317 // Wait for payload read FIFO empty
318 if !T::regs().gpsr().read().prdfe() {
319 return Ok(());
320 }
321 blocking_delay_ms(1);
322 }
323 Err(Error::FifoTimeout)
324 }
325}
326
327/// Possible Error Types for DSI HOST
328#[non_exhaustive]
329#[derive(Debug)]
330pub enum Error {
331 /// Waiting for FIFO empty flag timed out
332 FifoTimeout,
333 /// The specified `PacketType` is invalid for the selected operation
334 InvalidPacketType,
335 /// Provided read size does not match the read buffer length
336 InvalidReadSize,
337}
338
339impl<'d, T: Instance> Drop for DsiHost<'d, T> {
340 fn drop(&mut self) {}
341}
342
343trait SealedInstance: crate::rcc::SealedRccPeripheral {
344 fn regs() -> &'static crate::pac::dsihost::Dsihost;
345}
346
347/// DSI instance trait.
348#[allow(private_bounds)]
349pub trait Instance: SealedInstance + RccPeripheral + 'static {}
350
351pin_trait!(TePin, Instance);
352
353foreach_peripheral!(
354 (dsihost, $inst:ident) => {
355 impl crate::dsihost::SealedInstance for peripherals::$inst {
356 fn regs() -> &'static crate::pac::dsihost::Dsihost {
357 &crate::pac::$inst
358 }
359 }
360
361 impl crate::dsihost::Instance for peripherals::$inst {}
362 };
363);
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 1f4e9ab1e..1f92e8b2a 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -66,6 +66,10 @@ pub mod cryp;
66pub mod dac; 66pub mod dac;
67#[cfg(dcmi)] 67#[cfg(dcmi)]
68pub mod dcmi; 68pub mod dcmi;
69#[cfg(dsihost)]
70pub mod dsihost;
71#[cfg(ltdc)]
72pub mod ltdc;
69#[cfg(eth)] 73#[cfg(eth)]
70pub mod eth; 74pub mod eth;
71#[cfg(feature = "exti")] 75#[cfg(feature = "exti")]
diff --git a/embassy-stm32/src/ltdc.rs b/embassy-stm32/src/ltdc.rs
new file mode 100644
index 000000000..1cdf71e7e
--- /dev/null
+++ b/embassy-stm32/src/ltdc.rs
@@ -0,0 +1,134 @@
1//! LTDC
2use crate::rcc::RccPeripheral;
3use crate::{peripherals, Peripheral};
4use core::marker::PhantomData;
5
6/// LTDC driver.
7pub struct Ltdc<'d, T: Instance> {
8 _peri: PhantomData<&'d mut T>,
9}
10
11impl<'d, T: Instance> Ltdc<'d, T> {
12 /// Note: Full-Duplex modes are not supported at this time
13 pub fn new(
14 _peri: impl Peripheral<P = T> + 'd,
15 /*
16 clk: impl Peripheral<P = impl ClkPin<T>> + 'd,
17 hsync: impl Peripheral<P = impl HsyncPin<T>> + 'd,
18 vsync: impl Peripheral<P = impl VsyncPin<T>> + 'd,
19 b0: impl Peripheral<P = impl B0Pin<T>> + 'd,
20 b1: impl Peripheral<P = impl B1Pin<T>> + 'd,
21 b2: impl Peripheral<P = impl B2Pin<T>> + 'd,
22 b3: impl Peripheral<P = impl B3Pin<T>> + 'd,
23 b4: impl Peripheral<P = impl B4Pin<T>> + 'd,
24 b5: impl Peripheral<P = impl B5Pin<T>> + 'd,
25 b6: impl Peripheral<P = impl B6Pin<T>> + 'd,
26 b7: impl Peripheral<P = impl B7Pin<T>> + 'd,
27 g0: impl Peripheral<P = impl G0Pin<T>> + 'd,
28 g1: impl Peripheral<P = impl G1Pin<T>> + 'd,
29 g2: impl Peripheral<P = impl G2Pin<T>> + 'd,
30 g3: impl Peripheral<P = impl G3Pin<T>> + 'd,
31 g4: impl Peripheral<P = impl G4Pin<T>> + 'd,
32 g5: impl Peripheral<P = impl G5Pin<T>> + 'd,
33 g6: impl Peripheral<P = impl G6Pin<T>> + 'd,
34 g7: impl Peripheral<P = impl G7Pin<T>> + 'd,
35 r0: impl Peripheral<P = impl R0Pin<T>> + 'd,
36 r1: impl Peripheral<P = impl R1Pin<T>> + 'd,
37 r2: impl Peripheral<P = impl R2Pin<T>> + 'd,
38 r3: impl Peripheral<P = impl R3Pin<T>> + 'd,
39 r4: impl Peripheral<P = impl R4Pin<T>> + 'd,
40 r5: impl Peripheral<P = impl R5Pin<T>> + 'd,
41 r6: impl Peripheral<P = impl R6Pin<T>> + 'd,
42 r7: impl Peripheral<P = impl R7Pin<T>> + 'd,
43 */
44 ) -> Self {
45 //into_ref!(clk);
46
47 critical_section::with(|_cs| {
48 // RM says the pllsaidivr should only be changed when pllsai is off. But this could have other unintended side effects. So let's just give it a try like this.
49 // According to the debugger, this bit gets set, anyway.
50 stm32_metapac::RCC
51 .dckcfgr()
52 .modify(|w| w.set_pllsaidivr(stm32_metapac::rcc::vals::Pllsaidivr::DIV2));
53 });
54
55 T::enable_and_reset();
56
57 //new_pin!(clk, AFType::OutputPushPull, Speed::VeryHigh, Pull::None);
58
59 // Set Tearing Enable pin according to CubeMx example
60 //te.set_as_af_pull(te.af_num(), AFType::OutputPushPull, Pull::None);
61 //te.set_speed(Speed::Low);
62 /*
63 T::regs().wcr().modify(|w| {
64 w.set_dsien(true);
65 });
66 */
67 Self { _peri: PhantomData }
68 }
69
70 /// Set the enable bit in the control register and assert that it has been enabled
71 pub fn enable(&mut self) {
72 T::regs().gcr().modify(|w| w.set_ltdcen(true));
73 assert!(T::regs().gcr().read().ltdcen())
74 }
75
76 /// Unset the enable bit in the control register and assert that it has been disabled
77 pub fn disable(&mut self) {
78 T::regs().gcr().modify(|w| w.set_ltdcen(false));
79 assert!(!T::regs().gcr().read().ltdcen())
80 }
81}
82
83impl<'d, T: Instance> Drop for Ltdc<'d, T> {
84 fn drop(&mut self) {}
85}
86
87trait SealedInstance: crate::rcc::SealedRccPeripheral {
88 fn regs() -> &'static crate::pac::ltdc::Ltdc;
89}
90
91/// DSI instance trait.
92#[allow(private_bounds)]
93pub trait Instance: SealedInstance + RccPeripheral + 'static {}
94
95pin_trait!(ClkPin, Instance);
96pin_trait!(HsyncPin, Instance);
97pin_trait!(VsyncPin, Instance);
98pin_trait!(DePin, Instance);
99pin_trait!(R0Pin, Instance);
100pin_trait!(R1Pin, Instance);
101pin_trait!(R2Pin, Instance);
102pin_trait!(R3Pin, Instance);
103pin_trait!(R4Pin, Instance);
104pin_trait!(R5Pin, Instance);
105pin_trait!(R6Pin, Instance);
106pin_trait!(R7Pin, Instance);
107pin_trait!(G0Pin, Instance);
108pin_trait!(G1Pin, Instance);
109pin_trait!(G2Pin, Instance);
110pin_trait!(G3Pin, Instance);
111pin_trait!(G4Pin, Instance);
112pin_trait!(G5Pin, Instance);
113pin_trait!(G6Pin, Instance);
114pin_trait!(G7Pin, Instance);
115pin_trait!(B0Pin, Instance);
116pin_trait!(B1Pin, Instance);
117pin_trait!(B2Pin, Instance);
118pin_trait!(B3Pin, Instance);
119pin_trait!(B4Pin, Instance);
120pin_trait!(B5Pin, Instance);
121pin_trait!(B6Pin, Instance);
122pin_trait!(B7Pin, Instance);
123
124foreach_peripheral!(
125 (ltdc, $inst:ident) => {
126 impl crate::ltdc::SealedInstance for peripherals::$inst {
127 fn regs() -> &'static crate::pac::ltdc::Ltdc {
128 &crate::pac::$inst
129 }
130 }
131
132 impl crate::ltdc::Instance for peripherals::$inst {}
133 };
134);
diff --git a/embassy-stm32/src/rcc/f247.rs b/embassy-stm32/src/rcc/f247.rs
index e3ee9a039..640175f1f 100644
--- a/embassy-stm32/src/rcc/f247.rs
+++ b/embassy-stm32/src/rcc/f247.rs
@@ -277,7 +277,7 @@ pub(crate) unsafe fn init(config: Config) {
277 pclk2_tim: Some(pclk2_tim), 277 pclk2_tim: Some(pclk2_tim),
278 rtc: rtc, 278 rtc: rtc,
279 pll1_q: pll.q, 279 pll1_q: pll.q,
280 pll1_r: None, // TODO 280 pll1_r: pll.r,
281 281
282 #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))] 282 #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
283 plli2s1_p: plli2s.p, 283 plli2s1_p: plli2s.p,
@@ -297,6 +297,9 @@ pub(crate) unsafe fn init(config: Config) {
297 #[cfg(not(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7)))] 297 #[cfg(not(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7)))]
298 pllsai1_q: None, 298 pllsai1_q: None,
299 299
300 #[cfg(dsihost)]
301 dsi_phy: None, // DSI PLL clock not supported, don't call `RccPeripheral::frequency()` in the drivers
302
300 hsi_div488: hsi.map(|hsi| hsi/488u32), 303 hsi_div488: hsi.map(|hsi| hsi/488u32),
301 hsi_hse: None, 304 hsi_hse: None,
302 afif: None, 305 afif: None,
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index 5d47d400c..3cc8a96c8 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -677,6 +677,9 @@ pub(crate) unsafe fn init(config: Config) {
677 #[cfg(rcc_h50)] 677 #[cfg(rcc_h50)]
678 pll3_r: None, 678 pll3_r: None,
679 679
680 #[cfg(dsihost)]
681 dsi_phy: None, // DSI PLL clock not supported, don't call `RccPeripheral::frequency()` in the drivers
682
680 #[cfg(stm32h5)] 683 #[cfg(stm32h5)]
681 audioclk: None, 684 audioclk: None,
682 i2s_ckin: None, 685 i2s_ckin: None,
diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs
index c625948fb..1329a03ac 100644
--- a/embassy-stm32/src/rcc/l.rs
+++ b/embassy-stm32/src/rcc/l.rs
@@ -413,6 +413,9 @@ pub(crate) unsafe fn init(config: Config) {
413 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 413 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
414 pllsai2_r: pllsai2.r, 414 pllsai2_r: pllsai2.r,
415 415
416 #[cfg(dsihost)]
417 dsi_phy: None, // DSI PLL clock not supported, don't call `RccPeripheral::frequency()` in the drivers
418
416 rtc: rtc, 419 rtc: rtc,
417 420
418 // TODO 421 // TODO
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index 4013d0a46..6ec0911bb 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -289,6 +289,9 @@ pub(crate) unsafe fn init(config: Config) {
289 pll3_q: pll3.q, 289 pll3_q: pll3.q,
290 pll3_r: pll3.r, 290 pll3_r: pll3.r,
291 291
292 #[cfg(dsihost)]
293 dsi_phy: None, // DSI PLL clock not supported, don't call `RccPeripheral::frequency()` in the drivers
294
292 // TODO 295 // TODO
293 audioclk: None, 296 audioclk: None,
294 hsi48_div_2: None, 297 hsi48_div_2: None,