aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh1
-rw-r--r--embassy-stm32/build.rs16
-rw-r--r--embassy-stm32/src/dma/gpdma.rs293
-rw-r--r--embassy-stm32/src/dma/mod.rs29
-rw-r--r--embassy-stm32/src/spi/mod.rs87
-rw-r--r--embassy-stm32/src/traits.rs14
-rw-r--r--examples/stm32u5/src/bin/blinky.rs29
m---------stm32-data0
-rw-r--r--stm32-metapac-gen/src/data.rs1
-rw-r--r--stm32-metapac/src/metadata.rs1
-rw-r--r--tests/stm32/Cargo.toml13
-rw-r--r--tests/stm32/src/bin/gpio.rs2
-rw-r--r--tests/stm32/src/bin/spi.rs12
-rw-r--r--tests/stm32/src/bin/spi_dma.rs2
-rw-r--r--tests/stm32/src/bin/usart.rs2
-rw-r--r--tests/stm32/src/bin/usart_dma.rs2
16 files changed, 446 insertions, 58 deletions
diff --git a/ci.sh b/ci.sh
index 116b6a319..69fa08047 100755
--- a/ci.sh
+++ b/ci.sh
@@ -88,6 +88,7 @@ cargo batch \
88 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g071rb --out-dir out/tests/nucleo-stm32g071rb \ 88 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g071rb --out-dir out/tests/nucleo-stm32g071rb \
89 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --out-dir out/tests/nucleo-stm32h755zi \ 89 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --out-dir out/tests/nucleo-stm32h755zi \
90 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --out-dir out/tests/nucleo-stm32wb55rg \ 90 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --out-dir out/tests/nucleo-stm32wb55rg \
91 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585ai --out-dir out/tests/iot-stm32u585ai \
91 92
92 93
93function run_elf { 94function run_elf {
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 9125155c5..aa3e64131 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -109,7 +109,7 @@ fn main() {
109 109
110 for p in METADATA.peripherals { 110 for p in METADATA.peripherals {
111 if let Some(r) = &p.registers { 111 if let Some(r) = &p.registers {
112 if r.kind == "dma" || r.kind == "bdma" { 112 if r.kind == "dma" || r.kind == "bdma" || r.kind == "gpdma" {
113 if p.name == "BDMA1" { 113 if p.name == "BDMA1" {
114 // BDMA1 in H7 doesn't use DMAMUX, which breaks 114 // BDMA1 in H7 doesn't use DMAMUX, which breaks
115 continue; 115 continue;
@@ -214,7 +214,7 @@ fn main() {
214 // ======== 214 // ========
215 // Generate fns to enable GPIO, DMA in RCC 215 // Generate fns to enable GPIO, DMA in RCC
216 216
217 for kind in ["dma", "bdma", "dmamux", "gpio"] { 217 for kind in ["dma", "bdma", "dmamux", "gpdma", "gpio"] {
218 let mut gg = TokenStream::new(); 218 let mut gg = TokenStream::new();
219 219
220 for p in METADATA.peripherals { 220 for p in METADATA.peripherals {
@@ -528,11 +528,17 @@ fn main() {
528 let peri = format_ident!("{}", p.name); 528 let peri = format_ident!("{}", p.name);
529 529
530 let channel = if let Some(channel) = &ch.channel { 530 let channel = if let Some(channel) = &ch.channel {
531 // Chip with DMA/BDMA, without DMAMUX
531 let channel = format_ident!("{}", channel); 532 let channel = format_ident!("{}", channel);
532 quote!({channel: #channel}) 533 quote!({channel: #channel})
533 } else if let Some(dmamux) = &ch.dmamux { 534 } else if let Some(dmamux) = &ch.dmamux {
535 // Chip with DMAMUX
534 let dmamux = format_ident!("{}", dmamux); 536 let dmamux = format_ident!("{}", dmamux);
535 quote!({dmamux: #dmamux}) 537 quote!({dmamux: #dmamux})
538 } else if let Some(dma) = &ch.dma {
539 // Chip with GPDMA
540 let dma = format_ident!("{}", dma);
541 quote!({dma: #dma})
536 } else { 542 } else {
537 unreachable!(); 543 unreachable!();
538 }; 544 };
@@ -606,6 +612,7 @@ fn main() {
606 612
607 let mut dma_channel_count: usize = 0; 613 let mut dma_channel_count: usize = 0;
608 let mut bdma_channel_count: usize = 0; 614 let mut bdma_channel_count: usize = 0;
615 let mut gpdma_channel_count: usize = 0;
609 616
610 for ch in METADATA.dma_channels { 617 for ch in METADATA.dma_channels {
611 let mut row = Vec::new(); 618 let mut row = Vec::new();
@@ -626,6 +633,10 @@ fn main() {
626 num = bdma_channel_count; 633 num = bdma_channel_count;
627 bdma_channel_count += 1; 634 bdma_channel_count += 1;
628 } 635 }
636 "gpdma" => {
637 num = gpdma_channel_count;
638 gpdma_channel_count += 1;
639 }
629 _ => panic!("bad dma channel kind {}", bi.kind), 640 _ => panic!("bad dma channel kind {}", bi.kind),
630 } 641 }
631 642
@@ -650,6 +661,7 @@ fn main() {
650 g.extend(quote! { 661 g.extend(quote! {
651 pub(crate) const DMA_CHANNEL_COUNT: usize = #dma_channel_count; 662 pub(crate) const DMA_CHANNEL_COUNT: usize = #dma_channel_count;
652 pub(crate) const BDMA_CHANNEL_COUNT: usize = #bdma_channel_count; 663 pub(crate) const BDMA_CHANNEL_COUNT: usize = #bdma_channel_count;
664 pub(crate) const GPDMA_CHANNEL_COUNT: usize = #gpdma_channel_count;
653 }); 665 });
654 666
655 for irq in METADATA.interrupts { 667 for irq in METADATA.interrupts {
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
new file mode 100644
index 000000000..0cb986b32
--- /dev/null
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -0,0 +1,293 @@
1use core::sync::atomic::{fence, Ordering};
2use core::task::Waker;
3
4use embassy::interrupt::{Interrupt, InterruptExt};
5use embassy::waitqueue::AtomicWaker;
6
7use crate::_generated::GPDMA_CHANNEL_COUNT;
8use crate::interrupt;
9use crate::pac;
10use crate::pac::gpdma::{vals, Gpdma};
11
12use super::{Request, TransferOptions, Word, WordSize};
13
14impl From<WordSize> for vals::ChTr1Dw {
15 fn from(raw: WordSize) -> Self {
16 match raw {
17 WordSize::OneByte => Self::BYTE,
18 WordSize::TwoBytes => Self::HALFWORD,
19 WordSize::FourBytes => Self::WORD,
20 }
21 }
22}
23
24struct ChannelState {
25 waker: AtomicWaker,
26}
27
28impl ChannelState {
29 const fn new() -> Self {
30 Self {
31 waker: AtomicWaker::new(),
32 }
33 }
34}
35
36struct State {
37 channels: [ChannelState; GPDMA_CHANNEL_COUNT],
38}
39
40impl State {
41 const fn new() -> Self {
42 const CH: ChannelState = ChannelState::new();
43 Self {
44 channels: [CH; GPDMA_CHANNEL_COUNT],
45 }
46 }
47}
48
49static STATE: State = State::new();
50
51/// safety: must be called only once
52pub(crate) unsafe fn init() {
53 foreach_interrupt! {
54 ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => {
55 interrupt::$irq::steal().enable();
56 };
57 }
58 crate::_generated::init_gpdma();
59}
60
61foreach_dma_channel! {
62 ($channel_peri:ident, $dma_peri:ident, gpdma, $channel_num:expr, $index:expr, $dmamux:tt) => {
63 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
64 unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) {
65 let (ptr, len) = super::slice_ptr_parts(buf);
66 low_level_api::start_transfer(
67 pac::$dma_peri,
68 $channel_num,
69 request,
70 low_level_api::Dir::MemoryToPeripheral,
71 reg_addr as *const u32,
72 ptr as *mut u32,
73 len,
74 true,
75 W::bits(),
76 options,
77 )
78 }
79
80 unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) {
81 let buf = [repeated];
82 low_level_api::start_transfer(
83 pac::$dma_peri,
84 $channel_num,
85 request,
86 low_level_api::Dir::MemoryToPeripheral,
87 reg_addr as *const u32,
88 buf.as_ptr() as *mut u32,
89 count,
90 false,
91 W::bits(),
92 options,
93 )
94 }
95
96 unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *const W, buf: *mut [W], options: TransferOptions) {
97 let (ptr, len) = super::slice_ptr_parts_mut(buf);
98 low_level_api::start_transfer(
99 pac::$dma_peri,
100 $channel_num,
101 request,
102 low_level_api::Dir::PeripheralToMemory,
103 reg_addr as *const u32,
104 ptr as *mut u32,
105 len,
106 true,
107 W::bits(),
108 options,
109 );
110 }
111
112 unsafe fn start_double_buffered_read<W: Word>(
113 &mut self,
114 _request: Request,
115 _reg_addr: *const W,
116 _buffer0: *mut W,
117 _buffer1: *mut W,
118 _buffer_len: usize,
119 _options: TransferOptions,
120 ) {
121 panic!("Unsafe double buffered mode is unavailable on GPBDMA");
122 }
123
124 unsafe fn set_buffer0<W: Word>(&mut self, _buffer: *mut W) {
125 panic!("Unsafe double buffered mode is unavailable on GPBDMA");
126 }
127
128 unsafe fn set_buffer1<W: Word>(&mut self, _buffer: *mut W) {
129 panic!("Unsafe double buffered mode is unavailable on GPBDMA");
130 }
131
132 unsafe fn is_buffer0_accessible(&mut self) -> bool {
133 panic!("Unsafe double buffered mode is unavailable on GPBDMA");
134 }
135
136 fn request_stop(&mut self) {
137 unsafe {low_level_api::request_stop(pac::$dma_peri, $channel_num);}
138 }
139
140 fn is_running(&self) -> bool {
141 unsafe {low_level_api::is_running(pac::$dma_peri, $channel_num)}
142 }
143
144 fn remaining_transfers(&mut self) -> u16 {
145 unsafe {low_level_api::get_remaining_transfers(pac::$dma_peri, $channel_num)}
146 }
147
148 fn set_waker(&mut self, waker: &Waker) {
149 unsafe {low_level_api::set_waker($index, waker )}
150 }
151
152 fn on_irq() {
153 unsafe {
154 low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index);
155 }
156 }
157 }
158 impl crate::dma::Channel for crate::peripherals::$channel_peri { }
159 };
160}
161
162mod low_level_api {
163 use super::*;
164
165 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
166 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
167 pub enum Dir {
168 MemoryToPeripheral,
169 PeripheralToMemory,
170 }
171
172 pub unsafe fn start_transfer(
173 dma: Gpdma,
174 channel_number: u8,
175 request: Request,
176 dir: Dir,
177 peri_addr: *const u32,
178 mem_addr: *mut u32,
179 mem_len: usize,
180 incr_mem: bool,
181 data_size: WordSize,
182 _options: TransferOptions,
183 ) {
184 // "Preceding reads and writes cannot be moved past subsequent writes."
185 fence(Ordering::SeqCst);
186
187 let ch = dma.ch(channel_number as _);
188 ch.llr().write(|_| {}); // no linked list
189 ch.tr1().write(|w| {
190 w.set_sdw(data_size.into());
191 w.set_ddw(data_size.into());
192 w.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem);
193 w.set_dinc(dir == Dir::PeripheralToMemory && incr_mem);
194 });
195 ch.tr2().write(|w| {
196 w.set_dreq(match dir {
197 Dir::MemoryToPeripheral => vals::ChTr2Dreq::DESTINATIONPERIPHERAL,
198 Dir::PeripheralToMemory => vals::ChTr2Dreq::SOURCEPERIPHERAL,
199 });
200 w.set_reqsel(request);
201 });
202 ch.br1().write(|w| {
203 // BNDT is specified as bytes, not as number of transfers.
204 w.set_bndt((mem_len * data_size.bytes()) as u16)
205 });
206
207 match dir {
208 Dir::MemoryToPeripheral => {
209 ch.sar().write_value(mem_addr as _);
210 ch.dar().write_value(peri_addr as _);
211 }
212 Dir::PeripheralToMemory => {
213 ch.sar().write_value(peri_addr as _);
214 ch.dar().write_value(mem_addr as _);
215 }
216 }
217
218 ch.cr().write(|w| {
219 // Enable interrupts
220 w.set_tcie(true);
221 w.set_useie(true);
222 w.set_dteie(true);
223 w.set_suspie(true);
224
225 // Start it
226 w.set_en(true);
227 });
228 }
229
230 /// Stops the DMA channel.
231 pub unsafe fn request_stop(dma: Gpdma, channel_number: u8) {
232 // get a handle on the channel itself
233 let ch = dma.ch(channel_number as _);
234
235 // Disable the channel. Keep the IEs enabled so the irqs still fire.
236 ch.cr().write(|w| {
237 w.set_tcie(true);
238 w.set_useie(true);
239 w.set_dteie(true);
240 w.set_suspie(true);
241 });
242
243 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
244 fence(Ordering::SeqCst);
245 }
246
247 /// Gets the running status of the channel
248 pub unsafe fn is_running(dma: Gpdma, ch: u8) -> bool {
249 let ch = dma.ch(ch as _);
250 !ch.sr().read().idlef()
251 }
252
253 /// Gets the total remaining transfers for the channel
254 /// Note: this will be zero for transfers that completed without cancellation.
255 pub unsafe fn get_remaining_transfers(dma: Gpdma, ch: u8) -> u16 {
256 // get a handle on the channel itself
257 let ch = dma.ch(ch as _);
258 // read the remaining transfer count. If this is zero, the transfer completed fully.
259 ch.br1().read().bndt()
260 }
261
262 /// Sets the waker for the specified DMA channel
263 pub unsafe fn set_waker(state_number: usize, waker: &Waker) {
264 STATE.channels[state_number].waker.register(waker);
265 }
266
267 /// Safety: Must be called with a matching set of parameters for a valid dma channel
268 pub unsafe fn on_irq_inner(dma: Gpdma, channel_num: u8, state_index: u8) {
269 let channel_num = channel_num as usize;
270 let state_index = state_index as usize;
271
272 let ch = dma.ch(channel_num);
273 let sr = ch.sr().read();
274
275 if sr.dtef() {
276 panic!(
277 "DMA: data transfer error on DMA@{:08x} channel {}",
278 dma.0 as u32, channel_num
279 );
280 }
281 if sr.usef() {
282 panic!(
283 "DMA: user settings error on DMA@{:08x} channel {}",
284 dma.0 as u32, channel_num
285 );
286 }
287
288 if sr.suspf() || sr.tcf() {
289 ch.cr().write(|w| w.set_reset(true));
290 STATE.channels[state_index].waker.wake();
291 }
292 }
293}
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index f96ccbf6e..c19f7b3c7 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -4,6 +4,8 @@ pub(crate) mod bdma;
4pub(crate) mod dma; 4pub(crate) mod dma;
5#[cfg(dmamux)] 5#[cfg(dmamux)]
6mod dmamux; 6mod dmamux;
7#[cfg(gpdma)]
8mod gpdma;
7 9
8#[cfg(dmamux)] 10#[cfg(dmamux)]
9pub use dmamux::*; 11pub use dmamux::*;
@@ -24,9 +26,9 @@ pub mod low_level {
24 26
25pub(crate) use transfers::*; 27pub(crate) use transfers::*;
26 28
27#[cfg(any(bdma_v2, dma_v2, dmamux))] 29#[cfg(any(bdma_v2, dma_v2, dmamux, gpdma))]
28pub type Request = u8; 30pub type Request = u8;
29#[cfg(not(any(bdma_v2, dma_v2, dmamux)))] 31#[cfg(not(any(bdma_v2, dma_v2, dmamux, gpdma)))]
30pub type Request = (); 32pub type Request = ();
31 33
32pub(crate) mod sealed { 34pub(crate) mod sealed {
@@ -118,11 +120,24 @@ pub(crate) mod sealed {
118 } 120 }
119} 121}
120 122
123#[derive(Debug, Copy, Clone, PartialEq, Eq)]
124#[cfg_attr(feature = "defmt", derive(defmt::Format))]
121pub enum WordSize { 125pub enum WordSize {
122 OneByte, 126 OneByte,
123 TwoBytes, 127 TwoBytes,
124 FourBytes, 128 FourBytes,
125} 129}
130
131impl WordSize {
132 pub fn bytes(&self) -> usize {
133 match self {
134 Self::OneByte => 1,
135 Self::TwoBytes => 2,
136 Self::FourBytes => 4,
137 }
138 }
139}
140
126pub trait Word: sealed::Word { 141pub trait Word: sealed::Word {
127 fn bits() -> WordSize; 142 fn bits() -> WordSize;
128} 143}
@@ -148,7 +163,8 @@ impl Word for u32 {
148 } 163 }
149} 164}
150 165
151#[derive(Debug, PartialEq)] 166#[derive(Debug, Copy, Clone, PartialEq, Eq)]
167#[cfg_attr(feature = "defmt", derive(defmt::Format))]
152pub enum Burst { 168pub enum Burst {
153 /// Single transfer 169 /// Single transfer
154 Single, 170 Single,
@@ -160,7 +176,8 @@ pub enum Burst {
160 Incr16, 176 Incr16,
161} 177}
162 178
163#[derive(Debug, PartialEq)] 179#[derive(Debug, Copy, Clone, PartialEq, Eq)]
180#[cfg_attr(feature = "defmt", derive(defmt::Format))]
164pub enum FlowControl { 181pub enum FlowControl {
165 /// Flow control by DMA 182 /// Flow control by DMA
166 Dma, 183 Dma,
@@ -168,6 +185,8 @@ pub enum FlowControl {
168 Peripheral, 185 Peripheral,
169} 186}
170 187
188#[derive(Debug, Copy, Clone, PartialEq, Eq)]
189#[cfg_attr(feature = "defmt", derive(defmt::Format))]
171pub struct TransferOptions { 190pub struct TransferOptions {
172 /// Peripheral burst transfer configuration 191 /// Peripheral burst transfer configuration
173 pub pburst: Burst, 192 pub pburst: Burst,
@@ -299,6 +318,8 @@ pub(crate) unsafe fn init() {
299 dma::init(); 318 dma::init();
300 #[cfg(dmamux)] 319 #[cfg(dmamux)]
301 dmamux::init(); 320 dmamux::init();
321 #[cfg(gpdma)]
322 gpdma::init();
302} 323}
303 324
304// TODO: replace transmutes with core::ptr::metadata once it's stable 325// TODO: replace transmutes with core::ptr::metadata once it's stable
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index ea0c496db..23240ad82 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -100,13 +100,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
100 unborrow!(sck, mosi, miso); 100 unborrow!(sck, mosi, miso);
101 unsafe { 101 unsafe {
102 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 102 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
103 #[cfg(any(spi_v2, spi_v3))] 103 #[cfg(any(spi_v2, spi_v3, spi_v4))]
104 sck.set_speed(crate::gpio::Speed::VeryHigh); 104 sck.set_speed(crate::gpio::Speed::VeryHigh);
105 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); 105 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
106 #[cfg(any(spi_v2, spi_v3))] 106 #[cfg(any(spi_v2, spi_v3, spi_v4))]
107 mosi.set_speed(crate::gpio::Speed::VeryHigh); 107 mosi.set_speed(crate::gpio::Speed::VeryHigh);
108 miso.set_as_af(miso.af_num(), AFType::Input); 108 miso.set_as_af(miso.af_num(), AFType::Input);
109 #[cfg(any(spi_v2, spi_v3))] 109 #[cfg(any(spi_v2, spi_v3, spi_v4))]
110 miso.set_speed(crate::gpio::Speed::VeryHigh); 110 miso.set_speed(crate::gpio::Speed::VeryHigh);
111 } 111 }
112 112
@@ -137,10 +137,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
137 unborrow!(sck, miso); 137 unborrow!(sck, miso);
138 unsafe { 138 unsafe {
139 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 139 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
140 #[cfg(any(spi_v2, spi_v3))] 140 #[cfg(any(spi_v2, spi_v3, spi_v4))]
141 sck.set_speed(crate::gpio::Speed::VeryHigh); 141 sck.set_speed(crate::gpio::Speed::VeryHigh);
142 miso.set_as_af(miso.af_num(), AFType::Input); 142 miso.set_as_af(miso.af_num(), AFType::Input);
143 #[cfg(any(spi_v2, spi_v3))] 143 #[cfg(any(spi_v2, spi_v3, spi_v4))]
144 miso.set_speed(crate::gpio::Speed::VeryHigh); 144 miso.set_speed(crate::gpio::Speed::VeryHigh);
145 } 145 }
146 146
@@ -171,10 +171,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
171 unborrow!(sck, mosi); 171 unborrow!(sck, mosi);
172 unsafe { 172 unsafe {
173 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 173 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
174 #[cfg(any(spi_v2, spi_v3))] 174 #[cfg(any(spi_v2, spi_v3, spi_v4))]
175 sck.set_speed(crate::gpio::Speed::VeryHigh); 175 sck.set_speed(crate::gpio::Speed::VeryHigh);
176 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); 176 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
177 #[cfg(any(spi_v2, spi_v3))] 177 #[cfg(any(spi_v2, spi_v3, spi_v4))]
178 mosi.set_speed(crate::gpio::Speed::VeryHigh); 178 mosi.set_speed(crate::gpio::Speed::VeryHigh);
179 } 179 }
180 180
@@ -260,7 +260,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
260 w.set_spe(true); 260 w.set_spe(true);
261 }); 261 });
262 } 262 }
263 #[cfg(spi_v3)] 263 #[cfg(any(spi_v3, spi_v4))]
264 unsafe { 264 unsafe {
265 T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); 265 T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff);
266 T::REGS.cfg2().modify(|w| { 266 T::REGS.cfg2().modify(|w| {
@@ -285,7 +285,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
285 }); 285 });
286 T::REGS.cr2().modify(|w| { 286 T::REGS.cr2().modify(|w| {
287 w.set_tsize(0); 287 w.set_tsize(0);
288 w.set_tser(0);
289 }); 288 });
290 T::REGS.cr1().modify(|w| { 289 T::REGS.cr1().modify(|w| {
291 w.set_ssi(false); 290 w.set_ssi(false);
@@ -320,7 +319,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
320 }); 319 });
321 } 320 }
322 321
323 #[cfg(spi_v3)] 322 #[cfg(any(spi_v3, spi_v4))]
324 unsafe { 323 unsafe {
325 T::REGS.cfg2().modify(|w| { 324 T::REGS.cfg2().modify(|w| {
326 w.set_cpha(cpha); 325 w.set_cpha(cpha);
@@ -333,7 +332,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
333 pub fn get_current_config(&self) -> Config { 332 pub fn get_current_config(&self) -> Config {
334 #[cfg(any(spi_v1, spi_f1, spi_v2))] 333 #[cfg(any(spi_v1, spi_f1, spi_v2))]
335 let cfg = unsafe { T::REGS.cr1().read() }; 334 let cfg = unsafe { T::REGS.cr1().read() };
336 #[cfg(spi_v3)] 335 #[cfg(any(spi_v3, spi_v4))]
337 let cfg = unsafe { T::REGS.cfg2().read() }; 336 let cfg = unsafe { T::REGS.cfg2().read() };
338 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { 337 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
339 Polarity::IdleLow 338 Polarity::IdleLow
@@ -386,7 +385,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
386 w.set_spe(true); 385 w.set_spe(true);
387 }); 386 });
388 } 387 }
389 #[cfg(spi_v3)] 388 #[cfg(any(spi_v3, spi_v4))]
390 unsafe { 389 unsafe {
391 T::REGS.cr1().modify(|w| { 390 T::REGS.cr1().modify(|w| {
392 w.set_csusp(true); 391 w.set_csusp(true);
@@ -435,7 +434,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
435 T::REGS.cr1().modify(|w| { 434 T::REGS.cr1().modify(|w| {
436 w.set_spe(true); 435 w.set_spe(true);
437 }); 436 });
438 #[cfg(spi_v3)] 437 #[cfg(any(spi_v3, spi_v4))]
439 T::REGS.cr1().modify(|w| { 438 T::REGS.cr1().modify(|w| {
440 w.set_cstart(true); 439 w.set_cstart(true);
441 }); 440 });
@@ -466,7 +465,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
466 } 465 }
467 466
468 // SPIv3 clears rxfifo on SPE=0 467 // SPIv3 clears rxfifo on SPE=0
469 #[cfg(not(spi_v3))] 468 #[cfg(not(any(spi_v3, spi_v4)))]
470 flush_rx_fifo(T::REGS); 469 flush_rx_fifo(T::REGS);
471 470
472 let clock_byte_count = data.len(); 471 let clock_byte_count = data.len();
@@ -495,7 +494,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
495 T::REGS.cr1().modify(|w| { 494 T::REGS.cr1().modify(|w| {
496 w.set_spe(true); 495 w.set_spe(true);
497 }); 496 });
498 #[cfg(spi_v3)] 497 #[cfg(any(spi_v3, spi_v4))]
499 T::REGS.cr1().modify(|w| { 498 T::REGS.cr1().modify(|w| {
500 w.set_cstart(true); 499 w.set_cstart(true);
501 }); 500 });
@@ -533,7 +532,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
533 } 532 }
534 533
535 // SPIv3 clears rxfifo on SPE=0 534 // SPIv3 clears rxfifo on SPE=0
536 #[cfg(not(spi_v3))] 535 #[cfg(not(any(spi_v3, spi_v4)))]
537 flush_rx_fifo(T::REGS); 536 flush_rx_fifo(T::REGS);
538 537
539 let rx_request = self.rxdma.request(); 538 let rx_request = self.rxdma.request();
@@ -557,7 +556,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
557 T::REGS.cr1().modify(|w| { 556 T::REGS.cr1().modify(|w| {
558 w.set_spe(true); 557 w.set_spe(true);
559 }); 558 });
560 #[cfg(spi_v3)] 559 #[cfg(any(spi_v3, spi_v4))]
561 T::REGS.cr1().modify(|w| { 560 T::REGS.cr1().modify(|w| {
562 w.set_cstart(true); 561 w.set_cstart(true);
563 }); 562 });
@@ -642,9 +641,9 @@ impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
642 } 641 }
643} 642}
644 643
645#[cfg(not(spi_v3))] 644#[cfg(not(any(spi_v3, spi_v4)))]
646use vals::Br; 645use vals::Br;
647#[cfg(spi_v3)] 646#[cfg(any(spi_v3, spi_v4))]
648use vals::Mbr as Br; 647use vals::Mbr as Br;
649 648
650fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br { 649fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
@@ -670,17 +669,17 @@ trait RegsExt {
670 669
671impl RegsExt for Regs { 670impl RegsExt for Regs {
672 fn tx_ptr<W>(&self) -> *mut W { 671 fn tx_ptr<W>(&self) -> *mut W {
673 #[cfg(not(spi_v3))] 672 #[cfg(not(any(spi_v3, spi_v4)))]
674 let dr = self.dr(); 673 let dr = self.dr();
675 #[cfg(spi_v3)] 674 #[cfg(any(spi_v3, spi_v4))]
676 let dr = self.txdr(); 675 let dr = self.txdr();
677 dr.ptr() as *mut W 676 dr.ptr() as *mut W
678 } 677 }
679 678
680 fn rx_ptr<W>(&self) -> *mut W { 679 fn rx_ptr<W>(&self) -> *mut W {
681 #[cfg(not(spi_v3))] 680 #[cfg(not(any(spi_v3, spi_v4)))]
682 let dr = self.dr(); 681 let dr = self.dr();
683 #[cfg(spi_v3)] 682 #[cfg(any(spi_v3, spi_v4))]
684 let dr = self.rxdr(); 683 let dr = self.rxdr();
685 dr.ptr() as *mut W 684 dr.ptr() as *mut W
686 } 685 }
@@ -690,22 +689,22 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> {
690 if sr.ovr() { 689 if sr.ovr() {
691 return Err(Error::Overrun); 690 return Err(Error::Overrun);
692 } 691 }
693 #[cfg(not(any(spi_f1, spi_v3)))] 692 #[cfg(not(any(spi_f1, spi_v3, spi_v4)))]
694 if sr.fre() { 693 if sr.fre() {
695 return Err(Error::Framing); 694 return Err(Error::Framing);
696 } 695 }
697 #[cfg(spi_v3)] 696 #[cfg(any(spi_v3, spi_v4))]
698 if sr.tifre() { 697 if sr.tifre() {
699 return Err(Error::Framing); 698 return Err(Error::Framing);
700 } 699 }
701 if sr.modf() { 700 if sr.modf() {
702 return Err(Error::ModeFault); 701 return Err(Error::ModeFault);
703 } 702 }
704 #[cfg(not(spi_v3))] 703 #[cfg(not(any(spi_v3, spi_v4)))]
705 if sr.crcerr() { 704 if sr.crcerr() {
706 return Err(Error::Crc); 705 return Err(Error::Crc);
707 } 706 }
708 #[cfg(spi_v3)] 707 #[cfg(any(spi_v3, spi_v4))]
709 if sr.crce() { 708 if sr.crce() {
710 return Err(Error::Crc); 709 return Err(Error::Crc);
711 } 710 }
@@ -719,11 +718,11 @@ fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> {
719 718
720 check_error_flags(sr)?; 719 check_error_flags(sr)?;
721 720
722 #[cfg(not(spi_v3))] 721 #[cfg(not(any(spi_v3, spi_v4)))]
723 if sr.txe() { 722 if sr.txe() {
724 return Ok(()); 723 return Ok(());
725 } 724 }
726 #[cfg(spi_v3)] 725 #[cfg(any(spi_v3, spi_v4))]
727 if sr.txp() { 726 if sr.txp() {
728 return Ok(()); 727 return Ok(());
729 } 728 }
@@ -736,11 +735,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
736 735
737 check_error_flags(sr)?; 736 check_error_flags(sr)?;
738 737
739 #[cfg(not(spi_v3))] 738 #[cfg(not(any(spi_v3, spi_v4)))]
740 if sr.rxne() { 739 if sr.rxne() {
741 return Ok(()); 740 return Ok(());
742 } 741 }
743 #[cfg(spi_v3)] 742 #[cfg(any(spi_v3, spi_v4))]
744 if sr.rxp() { 743 if sr.rxp() {
745 return Ok(()); 744 return Ok(());
746 } 745 }
@@ -749,11 +748,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
749 748
750fn flush_rx_fifo(regs: Regs) { 749fn flush_rx_fifo(regs: Regs) {
751 unsafe { 750 unsafe {
752 #[cfg(not(spi_v3))] 751 #[cfg(not(any(spi_v3, spi_v4)))]
753 while regs.sr().read().rxne() { 752 while regs.sr().read().rxne() {
754 let _ = regs.dr().read(); 753 let _ = regs.dr().read();
755 } 754 }
756 #[cfg(spi_v3)] 755 #[cfg(any(spi_v3, spi_v4))]
757 while regs.sr().read().rxp() { 756 while regs.sr().read().rxp() {
758 let _ = regs.rxdr().read(); 757 let _ = regs.rxdr().read();
759 } 758 }
@@ -762,11 +761,11 @@ fn flush_rx_fifo(regs: Regs) {
762 761
763fn set_txdmaen(regs: Regs, val: bool) { 762fn set_txdmaen(regs: Regs, val: bool) {
764 unsafe { 763 unsafe {
765 #[cfg(not(spi_v3))] 764 #[cfg(not(any(spi_v3, spi_v4)))]
766 regs.cr2().modify(|reg| { 765 regs.cr2().modify(|reg| {
767 reg.set_txdmaen(val); 766 reg.set_txdmaen(val);
768 }); 767 });
769 #[cfg(spi_v3)] 768 #[cfg(any(spi_v3, spi_v4))]
770 regs.cfg1().modify(|reg| { 769 regs.cfg1().modify(|reg| {
771 reg.set_txdmaen(val); 770 reg.set_txdmaen(val);
772 }); 771 });
@@ -775,11 +774,11 @@ fn set_txdmaen(regs: Regs, val: bool) {
775 774
776fn set_rxdmaen(regs: Regs, val: bool) { 775fn set_rxdmaen(regs: Regs, val: bool) {
777 unsafe { 776 unsafe {
778 #[cfg(not(spi_v3))] 777 #[cfg(not(any(spi_v3, spi_v4)))]
779 regs.cr2().modify(|reg| { 778 regs.cr2().modify(|reg| {
780 reg.set_rxdmaen(val); 779 reg.set_rxdmaen(val);
781 }); 780 });
782 #[cfg(spi_v3)] 781 #[cfg(any(spi_v3, spi_v4))]
783 regs.cfg1().modify(|reg| { 782 regs.cfg1().modify(|reg| {
784 reg.set_rxdmaen(val); 783 reg.set_rxdmaen(val);
785 }); 784 });
@@ -791,21 +790,21 @@ fn finish_dma(regs: Regs) {
791 #[cfg(spi_v2)] 790 #[cfg(spi_v2)]
792 while regs.sr().read().ftlvl() > 0 {} 791 while regs.sr().read().ftlvl() > 0 {}
793 792
794 #[cfg(spi_v3)] 793 #[cfg(any(spi_v3, spi_v4))]
795 while !regs.sr().read().txc() {} 794 while !regs.sr().read().txc() {}
796 #[cfg(not(spi_v3))] 795 #[cfg(not(any(spi_v3, spi_v4)))]
797 while regs.sr().read().bsy() {} 796 while regs.sr().read().bsy() {}
798 797
799 regs.cr1().modify(|w| { 798 regs.cr1().modify(|w| {
800 w.set_spe(false); 799 w.set_spe(false);
801 }); 800 });
802 801
803 #[cfg(not(spi_v3))] 802 #[cfg(not(any(spi_v3, spi_v4)))]
804 regs.cr2().modify(|reg| { 803 regs.cr2().modify(|reg| {
805 reg.set_txdmaen(false); 804 reg.set_txdmaen(false);
806 reg.set_rxdmaen(false); 805 reg.set_rxdmaen(false);
807 }); 806 });
808 #[cfg(spi_v3)] 807 #[cfg(any(spi_v3, spi_v4))]
809 regs.cfg1().modify(|reg| { 808 regs.cfg1().modify(|reg| {
810 reg.set_txdmaen(false); 809 reg.set_txdmaen(false);
811 reg.set_rxdmaen(false); 810 reg.set_rxdmaen(false);
@@ -819,7 +818,7 @@ fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
819 unsafe { 818 unsafe {
820 ptr::write_volatile(regs.tx_ptr(), tx_word); 819 ptr::write_volatile(regs.tx_ptr(), tx_word);
821 820
822 #[cfg(spi_v3)] 821 #[cfg(any(spi_v3, spi_v4))]
823 regs.cr1().modify(|reg| reg.set_cstart(true)); 822 regs.cr1().modify(|reg| reg.set_cstart(true));
824 } 823 }
825 824
@@ -1018,7 +1017,7 @@ pub(crate) mod sealed {
1018 } 1017 }
1019 } 1018 }
1020 1019
1021 #[cfg(spi_v3)] 1020 #[cfg(any(spi_v3, spi_v4))]
1022 pub fn dsize(&self) -> u8 { 1021 pub fn dsize(&self) -> u8 {
1023 match self { 1022 match self {
1024 WordSize::EightBit => 0b0111, 1023 WordSize::EightBit => 0b0111,
@@ -1026,7 +1025,7 @@ pub(crate) mod sealed {
1026 } 1025 }
1027 } 1026 }
1028 1027
1029 #[cfg(spi_v3)] 1028 #[cfg(any(spi_v3, spi_v4))]
1030 pub fn _frxth(&self) -> vals::Fthlv { 1029 pub fn _frxth(&self) -> vals::Fthlv {
1031 match self { 1030 match self {
1032 WordSize::EightBit => vals::Fthlv::ONEFRAME, 1031 WordSize::EightBit => vals::Fthlv::ONEFRAME,
diff --git a/embassy-stm32/src/traits.rs b/embassy-stm32/src/traits.rs
index c733f4226..45cc4e725 100644
--- a/embassy-stm32/src/traits.rs
+++ b/embassy-stm32/src/traits.rs
@@ -42,7 +42,19 @@ macro_rules! dma_trait_impl {
42 } 42 }
43 }; 43 };
44 44
45 // No DMAMUX 45 // DMAMUX
46 (crate::$mod:ident::$trait:ident, $instance:ident, {dma: $dma:ident}, $request:expr) => {
47 impl<T> crate::$mod::$trait<crate::peripherals::$instance> for T
48 where
49 T: crate::dma::Channel,
50 {
51 fn request(&self) -> crate::dma::Request {
52 $request
53 }
54 }
55 };
56
57 // DMA/GPDMA, without DMAMUX
46 (crate::$mod:ident::$trait:ident, $instance:ident, {channel: $channel:ident}, $request:expr) => { 58 (crate::$mod:ident::$trait:ident, $instance:ident, {channel: $channel:ident}, $request:expr) => {
47 impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$channel { 59 impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$channel {
48 fn request(&self) -> crate::dma::Request { 60 fn request(&self) -> crate::dma::Request {
diff --git a/examples/stm32u5/src/bin/blinky.rs b/examples/stm32u5/src/bin/blinky.rs
new file mode 100644
index 000000000..e1bcccf58
--- /dev/null
+++ b/examples/stm32u5/src/bin/blinky.rs
@@ -0,0 +1,29 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use defmt_rtt as _;
7use embassy::executor::Spawner;
8use embassy::time::{Duration, Timer};
9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_stm32::Peripherals;
11// global logger
12use panic_probe as _;
13
14#[embassy::main]
15async fn main(_spawner: Spawner, p: Peripherals) -> ! {
16 info!("Hello World!");
17
18 let mut led = Output::new(p.PH7, Level::Low, Speed::Medium);
19
20 loop {
21 defmt::info!("on!");
22 led.set_low();
23 Timer::after(Duration::from_millis(200)).await;
24
25 defmt::info!("off!");
26 led.set_high();
27 Timer::after(Duration::from_millis(200)).await;
28 }
29}
diff --git a/stm32-data b/stm32-data
Subproject 8fb98d74620ab71fb9d0be2d800c427e0b77c46 Subproject 472ee98e8fdb11312392e47b16568c9d02fe654
diff --git a/stm32-metapac-gen/src/data.rs b/stm32-metapac-gen/src/data.rs
index 24f0bcf0d..a74c60ac0 100644
--- a/stm32-metapac-gen/src/data.rs
+++ b/stm32-metapac-gen/src/data.rs
@@ -104,6 +104,7 @@ pub struct PeripheralDmaChannel {
104 pub signal: String, 104 pub signal: String,
105 pub channel: Option<String>, 105 pub channel: Option<String>,
106 pub dmamux: Option<String>, 106 pub dmamux: Option<String>,
107 pub dma: Option<String>,
107 pub request: Option<u32>, 108 pub request: Option<u32>,
108} 109}
109 110
diff --git a/stm32-metapac/src/metadata.rs b/stm32-metapac/src/metadata.rs
index 150aa5956..23b759f6c 100644
--- a/stm32-metapac/src/metadata.rs
+++ b/stm32-metapac/src/metadata.rs
@@ -93,5 +93,6 @@ pub struct PeripheralDmaChannel {
93 pub signal: &'static str, 93 pub signal: &'static str,
94 pub channel: Option<&'static str>, 94 pub channel: Option<&'static str>,
95 pub dmamux: Option<&'static str>, 95 pub dmamux: Option<&'static str>,
96 pub dma: Option<&'static str>,
96 pub request: Option<u32>, 97 pub request: Option<u32>,
97} 98}
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 260ac223b..9bd087618 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -6,12 +6,13 @@ version = "0.1.0"
6resolver = "2" 6resolver = "2"
7 7
8[features] 8[features]
9stm32f103c8 = ["embassy-stm32/stm32f103c8"] 9stm32f103c8 = ["embassy-stm32/stm32f103c8"] # Blue Pill
10stm32f429zi = ["embassy-stm32/stm32f429zi"] 10stm32f429zi = ["embassy-stm32/stm32f429zi"] # Nucleo
11stm32g071rb = ["embassy-stm32/stm32g071rb"] 11stm32g071rb = ["embassy-stm32/stm32g071rb"] # Nucleo
12stm32g491re = ["embassy-stm32/stm32g491re"] 12stm32g491re = ["embassy-stm32/stm32g491re"] # Nucleo
13stm32h755zi = ["embassy-stm32/stm32h755zi-cm7"] 13stm32h755zi = ["embassy-stm32/stm32h755zi-cm7"] # Nucleo
14stm32wb55rg = ["embassy-stm32/stm32wb55rg"] 14stm32wb55rg = ["embassy-stm32/stm32wb55rg"] # Nucleo
15stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
15 16
16[dependencies] 17[dependencies]
17embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] } 18embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] }
diff --git a/tests/stm32/src/bin/gpio.rs b/tests/stm32/src/bin/gpio.rs
index 41c10d45f..c7991953f 100644
--- a/tests/stm32/src/bin/gpio.rs
+++ b/tests/stm32/src/bin/gpio.rs
@@ -28,6 +28,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
28 let (mut a, mut b) = (p.PA3, p.PA2); 28 let (mut a, mut b) = (p.PA3, p.PA2);
29 #[cfg(feature = "stm32h755zi")] 29 #[cfg(feature = "stm32h755zi")]
30 let (mut a, mut b) = (p.PB6, p.PB7); 30 let (mut a, mut b) = (p.PB6, p.PB7);
31 #[cfg(feature = "stm32u585ai")]
32 let (mut a, mut b) = (p.PD9, p.PD8);
31 33
32 // Test initial output 34 // Test initial output
33 { 35 {
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs
index b079472d5..049ba1e9f 100644
--- a/tests/stm32/src/bin/spi.rs
+++ b/tests/stm32/src/bin/spi.rs
@@ -16,10 +16,20 @@ use example_common::*;
16async fn main(_spawner: Spawner, p: Peripherals) { 16async fn main(_spawner: Spawner, p: Peripherals) {
17 info!("Hello World!"); 17 info!("Hello World!");
18 18
19 #[cfg(not(feature = "stm32h755zi"))] 19 #[cfg(feature = "stm32f103c8")]
20 let (sck, mosi, miso) = (p.PA5, p.PA7, p.PA6);
21 #[cfg(feature = "stm32f429zi")]
20 let (sck, mosi, miso) = (p.PA5, p.PA7, p.PA6); 22 let (sck, mosi, miso) = (p.PA5, p.PA7, p.PA6);
21 #[cfg(feature = "stm32h755zi")] 23 #[cfg(feature = "stm32h755zi")]
22 let (sck, mosi, miso) = (p.PA5, p.PB5, p.PA6); 24 let (sck, mosi, miso) = (p.PA5, p.PB5, p.PA6);
25 #[cfg(feature = "stm32g491re")]
26 let (sck, mosi, miso) = (p.PA5, p.PA7, p.PA6);
27 #[cfg(feature = "stm32g071rb")]
28 let (sck, mosi, miso) = (p.PA5, p.PA7, p.PA6);
29 #[cfg(feature = "stm32wb55rg")]
30 let (sck, mosi, miso) = (p.PA5, p.PA7, p.PA6);
31 #[cfg(feature = "stm32u585ai")]
32 let (sck, mosi, miso) = (p.PE13, p.PE15, p.PE14);
23 33
24 let mut spi = Spi::new( 34 let mut spi = Spi::new(
25 p.SPI1, 35 p.SPI1,
diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs
index f4f1994c0..64337886b 100644
--- a/tests/stm32/src/bin/spi_dma.rs
+++ b/tests/stm32/src/bin/spi_dma.rs
@@ -27,6 +27,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
27 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2); 27 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2);
28 #[cfg(feature = "stm32wb55rg")] 28 #[cfg(feature = "stm32wb55rg")]
29 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2); 29 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2);
30 #[cfg(feature = "stm32u585ai")]
31 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PE13, p.PE15, p.PE14, p.GPDMA1_CH0, p.GPDMA1_CH1);
30 32
31 let mut spi = Spi::new( 33 let mut spi = Spi::new(
32 p.SPI1, 34 p.SPI1,
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index 87a593ca5..c3468290e 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -35,6 +35,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
35 let (tx, rx, usart) = (p.PA9, p.PA10, p.USART1); // TODO this is wrong 35 let (tx, rx, usart) = (p.PA9, p.PA10, p.USART1); // TODO this is wrong
36 #[cfg(feature = "stm32h755zi")] 36 #[cfg(feature = "stm32h755zi")]
37 let (tx, rx, usart) = (p.PB6, p.PB7, p.USART1); 37 let (tx, rx, usart) = (p.PB6, p.PB7, p.USART1);
38 #[cfg(feature = "stm32u585ai")]
39 let (tx, rx, usart) = (p.PD8, p.PD9, p.USART3);
38 40
39 let config = Config::default(); 41 let config = Config::default();
40 let mut usart = Uart::new(usart, rx, tx, NoDma, NoDma, config); 42 let mut usart = Uart::new(usart, rx, tx, NoDma, NoDma, config);
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index 2565409e6..9946f4a56 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -34,6 +34,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
34 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH1, p.DMA1_CH2); // TODO this is wrong 34 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH1, p.DMA1_CH2); // TODO this is wrong
35 #[cfg(feature = "stm32h755zi")] 35 #[cfg(feature = "stm32h755zi")]
36 let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH0, p.DMA1_CH1); 36 let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH0, p.DMA1_CH1);
37 #[cfg(feature = "stm32u585ai")]
38 let (tx, rx, usart, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, p.GPDMA1_CH0, p.GPDMA1_CH1);
37 39
38 let config = Config::default(); 40 let config = Config::default();
39 let mut usart = Uart::new(usart, rx, tx, tx_dma, rx_dma, config); 41 let mut usart = Uart::new(usart, rx, tx, tx_dma, rx_dma, config);