aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/saadc.rs115
-rw-r--r--embassy-stm32/build.rs51
-rw-r--r--embassy-stm32/src/dma/bdma.rs40
-rw-r--r--embassy-stm32/src/dma/dma.rs36
-rw-r--r--embassy-stm32/src/dma/mod.rs5
-rw-r--r--examples/nrf/src/bin/saadc_continuous.rs59
-rw-r--r--examples/stm32l4/src/bin/spi_dma.rs2
m---------stm32-data0
-rw-r--r--tests/stm32/src/bin/spi_dma.rs6
-rw-r--r--tests/stm32/src/bin/usart_dma.rs6
10 files changed, 208 insertions, 112 deletions
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index 617c9e041..c4de7315f 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -10,7 +10,8 @@ use embassy_hal_common::unborrow;
10use futures::future::poll_fn; 10use futures::future::poll_fn;
11 11
12use crate::interrupt; 12use crate::interrupt;
13use crate::ppi::Task; 13use crate::ppi::{ConfigurableChannel, Event, Ppi, Task};
14use crate::timer::{Frequency, Instance as TimerInstance, Timer};
14use crate::{pac, peripherals}; 15use crate::{pac, peripherals};
15 16
16use pac::{saadc, SAADC}; 17use pac::{saadc, SAADC};
@@ -207,6 +208,11 @@ impl<'d, const N: usize> Saadc<'d, N> {
207 fn on_interrupt(_ctx: *mut ()) { 208 fn on_interrupt(_ctx: *mut ()) {
208 let r = Self::regs(); 209 let r = Self::regs();
209 210
211 if r.events_calibratedone.read().bits() != 0 {
212 r.intenclr.write(|w| w.calibratedone().clear());
213 WAKER.wake();
214 }
215
210 if r.events_end.read().bits() != 0 { 216 if r.events_end.read().bits() != 0 {
211 r.intenclr.write(|w| w.end().clear()); 217 r.intenclr.write(|w| w.end().clear());
212 WAKER.wake(); 218 WAKER.wake();
@@ -222,6 +228,35 @@ impl<'d, const N: usize> Saadc<'d, N> {
222 unsafe { &*SAADC::ptr() } 228 unsafe { &*SAADC::ptr() }
223 } 229 }
224 230
231 /// Perform SAADC calibration. Completes when done.
232 pub async fn calibrate(&self) {
233 let r = Self::regs();
234
235 // Reset and enable the end event
236 r.events_calibratedone.reset();
237 r.intenset.write(|w| w.calibratedone().set());
238
239 // Order is important
240 compiler_fence(Ordering::SeqCst);
241
242 r.tasks_calibrateoffset.write(|w| unsafe { w.bits(1) });
243
244 // Wait for 'calibratedone' event.
245 poll_fn(|cx| {
246 let r = Self::regs();
247
248 WAKER.register(cx.waker());
249
250 if r.events_calibratedone.read().bits() != 0 {
251 r.events_calibratedone.reset();
252 return Poll::Ready(());
253 }
254
255 Poll::Pending
256 })
257 .await;
258 }
259
225 /// One shot sampling. The buffer must be the same size as the number of channels configured. 260 /// One shot sampling. The buffer must be the same size as the number of channels configured.
226 pub async fn sample(&mut self, buf: &mut [i16; N]) { 261 pub async fn sample(&mut self, buf: &mut [i16; N]) {
227 let r = Self::regs(); 262 let r = Self::regs();
@@ -263,29 +298,77 @@ impl<'d, const N: usize> Saadc<'d, N> {
263 298
264 /// Continuous sampling with double buffers. 299 /// Continuous sampling with double buffers.
265 /// 300 ///
266 /// A task-driven approach to driving TASK_SAMPLE is expected. With a task 301 /// A TIMER and two PPI peripherals are passed in so that precise sampling
267 /// driven approach, multiple channels can be used. 302 /// can be attained. The sampling interval is expressed by selecting a
303 /// timer clock frequency to use along with a counter threshold to be reached.
304 /// For example, 1KHz can be achieved using a frequency of 1MHz and a counter
305 /// threshold of 1000.
268 /// 306 ///
269 /// A sampler closure is provided that receives the buffer of samples, noting 307 /// A sampler closure is provided that receives the buffer of samples, noting
270 /// that the size of this buffer can be less than the original buffer's size. 308 /// that the size of this buffer can be less than the original buffer's size.
271 /// A command is return from the closure that indicates whether the sampling 309 /// A command is return from the closure that indicates whether the sampling
272 /// should continue or stop. 310 /// should continue or stop.
273 pub async fn run_task_sampler<S, const N0: usize>( 311 ///
312 /// NOTE: The time spent within the callback supplied should not exceed the time
313 /// taken to acquire the samples into a single buffer. You should measure the
314 /// time taken by the callback and set the sample buffer size accordingly.
315 /// Exceeding this time can lead to samples becoming dropped.
316 pub async fn run_task_sampler<S, T: TimerInstance, const N0: usize>(
274 &mut self, 317 &mut self,
318 timer: &mut T,
319 ppi_ch1: &mut impl ConfigurableChannel,
320 ppi_ch2: &mut impl ConfigurableChannel,
321 frequency: Frequency,
322 sample_counter: u32,
275 bufs: &mut [[[i16; N]; N0]; 2], 323 bufs: &mut [[[i16; N]; N0]; 2],
276 sampler: S, 324 sampler: S,
277 ) where 325 ) where
278 S: FnMut(&[[i16; N]]) -> SamplerState, 326 S: FnMut(&[[i16; N]]) -> SamplerState,
279 { 327 {
280 self.run_sampler(bufs, None, sampler).await; 328 let r = Self::regs();
329
330 // We want the task start to effectively short with the last one ending so
331 // we don't miss any samples. It'd be great for the SAADC to offer a SHORTS
332 // register instead, but it doesn't, so we must use PPI.
333 let mut start_ppi = Ppi::new_one_to_one(
334 ppi_ch1,
335 Event::from_reg(&r.events_end),
336 Task::from_reg(&r.tasks_start),
337 );
338 start_ppi.enable();
339
340 let mut timer = Timer::new(timer);
341 timer.set_frequency(frequency);
342 timer.cc(0).write(sample_counter);
343 timer.cc(0).short_compare_clear();
344
345 let mut sample_ppi = Ppi::new_one_to_one(
346 ppi_ch2,
347 timer.cc(0).event_compare(),
348 Task::from_reg(&r.tasks_sample),
349 );
350
351 timer.start();
352
353 self.run_sampler(
354 bufs,
355 None,
356 || {
357 sample_ppi.enable();
358 },
359 sampler,
360 )
361 .await;
281 } 362 }
282 363
283 async fn run_sampler<S, const N0: usize>( 364 async fn run_sampler<I, S, const N0: usize>(
284 &mut self, 365 &mut self,
285 bufs: &mut [[[i16; N]; N0]; 2], 366 bufs: &mut [[[i16; N]; N0]; 2],
286 sample_rate_divisor: Option<u16>, 367 sample_rate_divisor: Option<u16>,
368 mut init: I,
287 mut sampler: S, 369 mut sampler: S,
288 ) where 370 ) where
371 I: FnMut(),
289 S: FnMut(&[[i16; N]]) -> SamplerState, 372 S: FnMut(&[[i16; N]]) -> SamplerState,
290 { 373 {
291 let r = Self::regs(); 374 let r = Self::regs();
@@ -330,6 +413,8 @@ impl<'d, const N: usize> Saadc<'d, N> {
330 413
331 r.tasks_start.write(|w| unsafe { w.bits(1) }); 414 r.tasks_start.write(|w| unsafe { w.bits(1) });
332 415
416 let mut inited = false;
417
333 let mut current_buffer = 0; 418 let mut current_buffer = 0;
334 419
335 // Wait for events and complete when the sampler indicates it has had enough. 420 // Wait for events and complete when the sampler indicates it has had enough.
@@ -347,7 +432,6 @@ impl<'d, const N: usize> Saadc<'d, N> {
347 if sampler(&bufs[current_buffer]) == SamplerState::Sampled { 432 if sampler(&bufs[current_buffer]) == SamplerState::Sampled {
348 let next_buffer = 1 - current_buffer; 433 let next_buffer = 1 - current_buffer;
349 current_buffer = next_buffer; 434 current_buffer = next_buffer;
350 r.tasks_start.write(|w| unsafe { w.bits(1) });
351 } else { 435 } else {
352 return Poll::Ready(()); 436 return Poll::Ready(());
353 }; 437 };
@@ -357,6 +441,11 @@ impl<'d, const N: usize> Saadc<'d, N> {
357 r.events_started.reset(); 441 r.events_started.reset();
358 r.intenset.write(|w| w.started().set()); 442 r.intenset.write(|w| w.started().set());
359 443
444 if !inited {
445 init();
446 inited = true;
447 }
448
360 let next_buffer = 1 - current_buffer; 449 let next_buffer = 1 - current_buffer;
361 r.result 450 r.result
362 .ptr 451 .ptr
@@ -367,26 +456,20 @@ impl<'d, const N: usize> Saadc<'d, N> {
367 }) 456 })
368 .await; 457 .await;
369 } 458 }
370
371 /// Return the sample task for use with PPI
372 pub fn task_sample(&self) -> Task {
373 let r = Self::regs();
374 Task::from_reg(&r.tasks_sample)
375 }
376} 459}
377 460
378impl<'d> Saadc<'d, 1> { 461impl<'d> Saadc<'d, 1> {
379 /// Continuous sampling on a single channel with double buffers. 462 /// Continuous sampling on a single channel with double buffers.
380 /// 463 ///
381 /// The internal clock is to be used with a sample rate expressed as a divisor of 464 /// The internal clock is to be used with a sample rate expressed as a divisor of
382 /// 16MHz, ranging from 80..2047. For example, 1600 represnts a sample rate of 10KHz 465 /// 16MHz, ranging from 80..2047. For example, 1600 represents a sample rate of 10KHz
383 /// given 16_000_000 / 10_000_000 = 1600. 466 /// given 16_000_000 / 10_000_000 = 1600.
384 /// 467 ///
385 /// A sampler closure is provided that receives the buffer of samples, noting 468 /// A sampler closure is provided that receives the buffer of samples, noting
386 /// that the size of this buffer can be less than the original buffer's size. 469 /// that the size of this buffer can be less than the original buffer's size.
387 /// A command is return from the closure that indicates whether the sampling 470 /// A command is return from the closure that indicates whether the sampling
388 /// should continue or stop. 471 /// should continue or stop.
389 pub async fn run_timer_sampler<S, const N0: usize>( 472 pub async fn run_timer_sampler<I, S, const N0: usize>(
390 &mut self, 473 &mut self,
391 bufs: &mut [[[i16; 1]; N0]; 2], 474 bufs: &mut [[[i16; 1]; N0]; 2],
392 sample_rate_divisor: u16, 475 sample_rate_divisor: u16,
@@ -394,7 +477,7 @@ impl<'d> Saadc<'d, 1> {
394 ) where 477 ) where
395 S: FnMut(&[[i16; 1]]) -> SamplerState, 478 S: FnMut(&[[i16; 1]]) -> SamplerState,
396 { 479 {
397 self.run_sampler(bufs, Some(sample_rate_divisor), sampler) 480 self.run_sampler(bufs, Some(sample_rate_divisor), || {}, sampler)
398 .await; 481 .await;
399 } 482 }
400} 483}
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 02d47da81..8b64aaaac 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -105,46 +105,41 @@ fn main() {
105 // ======== 105 // ========
106 // Generate DMA IRQs. 106 // Generate DMA IRQs.
107 107
108 let mut dma_irqs: HashSet<&str> = HashSet::new(); 108 let mut dma_irqs: HashMap<&str, Vec<(&str, &str)>> = HashMap::new();
109 let mut bdma_irqs: HashSet<&str> = HashSet::new();
110 109
111 for p in METADATA.peripherals { 110 for p in METADATA.peripherals {
112 if let Some(r) = &p.registers { 111 if let Some(r) = &p.registers {
113 match r.kind { 112 if r.kind == "dma" || r.kind == "bdma" {
114 "dma" => { 113 if p.name == "BDMA1" {
115 for irq in p.interrupts { 114 // BDMA1 in H7 doesn't use DMAMUX, which breaks
116 dma_irqs.insert(irq.interrupt); 115 continue;
117 }
118 } 116 }
119 "bdma" => { 117 for irq in p.interrupts {
120 for irq in p.interrupts { 118 dma_irqs
121 bdma_irqs.insert(irq.interrupt); 119 .entry(irq.interrupt)
122 } 120 .or_default()
121 .push((p.name, irq.signal));
123 } 122 }
124 _ => {}
125 } 123 }
126 } 124 }
127 } 125 }
128 126
129 let tokens: Vec<_> = dma_irqs.iter().map(|s| format_ident!("{}", s)).collect(); 127 for (irq, channels) in dma_irqs {
130 g.extend(quote! { 128 let irq = format_ident!("{}", irq);
131 #(
132 #[crate::interrupt]
133 unsafe fn #tokens () {
134 crate::dma::dma::on_irq();
135 }
136 )*
137 });
138 129
139 let tokens: Vec<_> = bdma_irqs.iter().map(|s| format_ident!("{}", s)).collect(); 130 let channels = channels
140 g.extend(quote! { 131 .iter()
141 #( 132 .map(|(dma, ch)| format_ident!("{}_{}", dma, ch));
133
134 g.extend(quote! {
142 #[crate::interrupt] 135 #[crate::interrupt]
143 unsafe fn #tokens () { 136 unsafe fn #irq () {
144 crate::dma::bdma::on_irq(); 137 #(
138 <crate::peripherals::#channels as crate::dma::sealed::Channel>::on_irq();
139 )*
145 } 140 }
146 )* 141 });
147 }); 142 }
148 143
149 // ======== 144 // ========
150 // Generate RccPeripheral impls 145 // Generate RccPeripheral impls
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 105bea50e..ec557da30 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -38,26 +38,6 @@ impl State {
38 38
39static STATE: State = State::new(); 39static STATE: State = State::new();
40 40
41pub(crate) unsafe fn on_irq() {
42 foreach_peripheral! {
43 (bdma, BDMA1) => {
44 // BDMA1 in H7 doesn't use DMAMUX, which breaks
45 };
46 (bdma, $dma:ident) => {
47 let isr = pac::$dma.isr().read();
48 foreach_dma_channel! {
49 ($channel_peri:ident, $dma, bdma, $channel_num:expr, $index:expr, $dmamux:tt) => {
50 let cr = pac::$dma.ch($channel_num).cr();
51 if isr.tcif($channel_num) && cr.read().tcie() {
52 cr.write(|_| ()); // Disable channel interrupts with the default value.
53 STATE.ch_wakers[$index].wake();
54 }
55 };
56 }
57 };
58 }
59}
60
61/// safety: must be called only once 41/// safety: must be called only once
62pub(crate) unsafe fn init() { 42pub(crate) unsafe fn init() {
63 foreach_interrupt! { 43 foreach_interrupt! {
@@ -150,6 +130,12 @@ foreach_dma_channel! {
150 fn set_waker(&mut self, waker: &Waker) { 130 fn set_waker(&mut self, waker: &Waker) {
151 unsafe { low_level_api::set_waker($index, waker) } 131 unsafe { low_level_api::set_waker($index, waker) }
152 } 132 }
133
134 fn on_irq() {
135 unsafe {
136 low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index);
137 }
138 }
153 } 139 }
154 140
155 impl crate::dma::Channel for crate::peripherals::$channel_peri {} 141 impl crate::dma::Channel for crate::peripherals::$channel_peri {}
@@ -243,4 +229,18 @@ mod low_level_api {
243 w.set_teif(channel_number as _, true); 229 w.set_teif(channel_number as _, true);
244 }); 230 });
245 } 231 }
232
233 /// Safety: Must be called with a matching set of parameters for a valid dma channel
234 pub unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: u8, index: u8) {
235 let channel_num = channel_num as usize;
236 let index = index as usize;
237
238 let isr = dma.isr().read();
239 let cr = dma.ch(channel_num).cr();
240
241 if isr.tcif(channel_num) && cr.read().tcie() {
242 cr.write(|_| ()); // Disable channel interrupts with the default value.
243 STATE.ch_wakers[index].wake();
244 }
245 }
246} 246}
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 95a6eea2f..9ef7e4288 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -36,22 +36,6 @@ impl State {
36 36
37static STATE: State = State::new(); 37static STATE: State = State::new();
38 38
39pub(crate) unsafe fn on_irq() {
40 foreach_peripheral! {
41 (dma, $dma:ident) => {
42 foreach_dma_channel! {
43 ($channel_peri:ident, $dma, dma, $channel_num:expr, $index:expr, $dmamux:tt) => {
44 let cr = pac::$dma.st($channel_num).cr();
45 if pac::$dma.isr($channel_num/4).read().tcif($channel_num%4) && cr.read().tcie() {
46 cr.write(|_| ()); // Disable channel interrupts with the default value.
47 STATE.ch_wakers[$index].wake();
48 }
49 };
50 }
51 };
52 }
53}
54
55/// safety: must be called only once 39/// safety: must be called only once
56pub(crate) unsafe fn init() { 40pub(crate) unsafe fn init() {
57 foreach_interrupt! { 41 foreach_interrupt! {
@@ -137,6 +121,12 @@ foreach_dma_channel! {
137 fn set_waker(&mut self, waker: &Waker) { 121 fn set_waker(&mut self, waker: &Waker) {
138 unsafe {low_level_api::set_waker($index, waker )} 122 unsafe {low_level_api::set_waker($index, waker )}
139 } 123 }
124
125 fn on_irq() {
126 unsafe {
127 low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index);
128 }
129 }
140 } 130 }
141 131
142 impl crate::dma::Channel for crate::peripherals::$channel_peri { } 132 impl crate::dma::Channel for crate::peripherals::$channel_peri { }
@@ -240,4 +230,18 @@ mod low_level_api {
240 w.set_teif(isrbit, true); 230 w.set_teif(isrbit, true);
241 }); 231 });
242 } 232 }
233
234 /// Safety: Must be called with a matching set of parameters for a valid dma channel
235 pub unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: u8, index: u8) {
236 let channel_num = channel_num as usize;
237 let index = index as usize;
238
239 let cr = dma.st(channel_num).cr();
240 let isr = dma.isr(channel_num / 4).read();
241
242 if isr.tcif(channel_num % 4) && cr.read().tcie() {
243 cr.write(|_| ()); // Disable channel interrupts with the default value.
244 STATE.ch_wakers[index].wake();
245 }
246 }
243} 247}
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 6bca969c8..4768a448c 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -88,6 +88,11 @@ pub(crate) mod sealed {
88 88
89 /// Sets the waker that is called when this channel stops (either completed or manually stopped) 89 /// Sets the waker that is called when this channel stops (either completed or manually stopped)
90 fn set_waker(&mut self, waker: &Waker); 90 fn set_waker(&mut self, waker: &Waker);
91
92 /// This is called when this channel triggers an interrupt.
93 /// Note: Because some channels share an interrupt, this function might be
94 /// called for a channel that didn't trigger an interrupt.
95 fn on_irq();
91 } 96 }
92} 97}
93 98
diff --git a/examples/nrf/src/bin/saadc_continuous.rs b/examples/nrf/src/bin/saadc_continuous.rs
index 81559237b..bdf552fba 100644
--- a/examples/nrf/src/bin/saadc_continuous.rs
+++ b/examples/nrf/src/bin/saadc_continuous.rs
@@ -5,9 +5,9 @@
5#[path = "../example_common.rs"] 5#[path = "../example_common.rs"]
6mod example_common; 6mod example_common;
7use embassy::executor::Spawner; 7use embassy::executor::Spawner;
8use embassy_nrf::ppi::Ppi; 8use embassy::time::Duration;
9use embassy_nrf::saadc::{ChannelConfig, Config, Saadc, SamplerState}; 9use embassy_nrf::saadc::{ChannelConfig, Config, Saadc, SamplerState};
10use embassy_nrf::timer::{Frequency, Timer}; 10use embassy_nrf::timer::Frequency;
11use embassy_nrf::{interrupt, Peripherals}; 11use embassy_nrf::{interrupt, Peripherals};
12use example_common::*; 12use example_common::*;
13 13
@@ -26,34 +26,43 @@ async fn main(_spawner: Spawner, mut p: Peripherals) {
26 [channel_1_config, channel_2_config, channel_3_config], 26 [channel_1_config, channel_2_config, channel_3_config],
27 ); 27 );
28 28
29 let mut timer = Timer::new(p.TIMER0); 29 // This delay demonstrates that starting the timer prior to running
30 timer.set_frequency(Frequency::F1MHz); 30 // the task sampler is benign given the calibration that follows.
31 timer.cc(0).write(100); // We want to sample at 10KHz 31 embassy::time::Timer::after(Duration::from_millis(500)).await;
32 timer.cc(0).short_compare_clear(); 32 saadc.calibrate().await;
33 33
34 let mut ppi = Ppi::new_one_to_one(p.PPI_CH0, timer.cc(0).event_compare(), saadc.task_sample()); 34 let mut bufs = [[[0; 3]; 500]; 2];
35 ppi.enable();
36
37 timer.start();
38
39 let mut bufs = [[[0; 3]; 50]; 2];
40 35
41 let mut c = 0; 36 let mut c = 0;
42 let mut a: i32 = 0; 37 let mut a: i32 = 0;
43 38
44 saadc 39 saadc
45 .run_task_sampler(&mut bufs, move |buf| { 40 .run_task_sampler(
46 for b in buf { 41 &mut p.TIMER0,
47 a += b[0] as i32; 42 &mut p.PPI_CH0,
48 } 43 &mut p.PPI_CH1,
49 c += buf.len(); 44 Frequency::F1MHz,
50 if c > 10000 { 45 1000, // We want to sample at 1KHz
51 a = a / c as i32; 46 &mut bufs,
52 info!("channel 1: {=i32}", a); 47 move |buf| {
53 c = 0; 48 // NOTE: It is important that the time spent within this callback
54 a = 0; 49 // does not exceed the time taken to acquire the 1500 samples we
55 } 50 // have in this example, which would be 10us + 2us per
56 SamplerState::Sampled 51 // sample * 1500 = 18ms. You need to measure the time taken here
57 }) 52 // and set the sample buffer size accordingly. Exceeding this
53 // time can lead to the peripheral re-writing the other buffer.
54 for b in buf {
55 a += b[0] as i32;
56 }
57 c += buf.len();
58 if c > 1000 {
59 a = a / c as i32;
60 info!("channel 1: {=i32}", a);
61 c = 0;
62 a = 0;
63 }
64 SamplerState::Sampled
65 },
66 )
58 .await; 67 .await;
59} 68}
diff --git a/examples/stm32l4/src/bin/spi_dma.rs b/examples/stm32l4/src/bin/spi_dma.rs
index b4d5091b2..a9327f8fe 100644
--- a/examples/stm32l4/src/bin/spi_dma.rs
+++ b/examples/stm32l4/src/bin/spi_dma.rs
@@ -21,8 +21,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
21 p.PC10, 21 p.PC10,
22 p.PC12, 22 p.PC12,
23 p.PC11, 23 p.PC11,
24 p.DMA1_CH0,
25 p.DMA1_CH1, 24 p.DMA1_CH1,
25 p.DMA1_CH2,
26 Hertz(1_000_000), 26 Hertz(1_000_000),
27 Config::default(), 27 Config::default(),
28 ); 28 );
diff --git a/stm32-data b/stm32-data
Subproject ad77937fb81628b982d2a674a88d983ec020fec Subproject d3e8a2fe63eeb403102559f3f9917d9fcf27e1a
diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs
index f224d3446..59a5bcd0c 100644
--- a/tests/stm32/src/bin/spi_dma.rs
+++ b/tests/stm32/src/bin/spi_dma.rs
@@ -22,11 +22,11 @@ async fn main(_spawner: Spawner, p: Peripherals) {
22 #[cfg(feature = "stm32h755zi")] 22 #[cfg(feature = "stm32h755zi")]
23 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PB5, p.PA6, p.DMA1_CH0, p.DMA1_CH1); 23 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PB5, p.PA6, p.DMA1_CH0, p.DMA1_CH1);
24 #[cfg(feature = "stm32g491re")] 24 #[cfg(feature = "stm32g491re")]
25 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH0, p.DMA1_CH1); 25 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2);
26 #[cfg(feature = "stm32g071rb")] 26 #[cfg(feature = "stm32g071rb")]
27 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH0, p.DMA1_CH1); 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_CH0, p.DMA1_CH1); 29 let (sck, mosi, miso, tx_dma, rx_dma) = (p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2);
30 30
31 let mut spi = Spi::new( 31 let mut spi = Spi::new(
32 p.SPI1, 32 p.SPI1,
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index 3cf9c7860..2565409e6 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -25,13 +25,13 @@ async fn main(_spawner: Spawner, p: Peripherals) {
25 #[cfg(feature = "stm32f103c8")] 25 #[cfg(feature = "stm32f103c8")]
26 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH4, p.DMA1_CH5); 26 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH4, p.DMA1_CH5);
27 #[cfg(feature = "stm32g491re")] 27 #[cfg(feature = "stm32g491re")]
28 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH0, p.DMA1_CH1); 28 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
29 #[cfg(feature = "stm32g071rb")] 29 #[cfg(feature = "stm32g071rb")]
30 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH0, p.DMA1_CH1); 30 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
31 #[cfg(feature = "stm32f429zi")] 31 #[cfg(feature = "stm32f429zi")]
32 let (tx, rx, usart, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, p.DMA2_CH6, p.DMA2_CH1); 32 let (tx, rx, usart, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, p.DMA2_CH6, p.DMA2_CH1);
33 #[cfg(feature = "stm32wb55rg")] 33 #[cfg(feature = "stm32wb55rg")]
34 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH0, p.DMA1_CH1); // 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 37