aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs
new file mode 100644
index 000000000..992bed573
--- /dev/null
+++ b/examples/stm32f4/src/bin/adc_dma.rs
@@ -0,0 +1,83 @@
1#![no_std]
2#![no_main]
3use cortex_m::singleton;
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, RingBufferedAdc, SampleTime, Sequence};
7use embassy_stm32::Peripherals;
8use embassy_time::Instant;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(spawner: Spawner) {
13 let p = embassy_stm32::init(Default::default());
14 spawner.must_spawn(adc_task(p));
15}
16
17#[embassy_executor::task]
18async fn adc_task(mut p: Peripherals) {
19 const ADC_BUF_SIZE: usize = 1024;
20 let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap();
21 let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap();
22
23 let adc = Adc::new(p.ADC1);
24 let adc2 = Adc::new(p.ADC2);
25
26 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(p.DMA2_CH0, adc_data);
27 let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(p.DMA2_CH2, adc_data2);
28
29 adc.set_sample_sequence(Sequence::One, &mut p.PA0, SampleTime::CYCLES112);
30 adc.set_sample_sequence(Sequence::Two, &mut p.PA2, SampleTime::CYCLES112);
31 adc2.set_sample_sequence(Sequence::One, &mut p.PA1, SampleTime::CYCLES112);
32 adc2.set_sample_sequence(Sequence::Two, &mut p.PA3, SampleTime::CYCLES112);
33
34 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around
35 // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of
36 // what channel is at what index is lost. The buffer must be cleared and reset. This *is* handled here, but allowing this to happen will cause
37 // a reduction of performance as each time the buffer is reset, the adc & dma buffer must be restarted.
38
39 // An interrupt executor with a higher priority than other tasks may be a good approach here, allowing this task to wake and read the buffer most
40 // frequently.
41 let mut tic = Instant::now();
42 let mut buffer1 = [0u16; 512];
43 let mut buffer2 = [0u16; 512];
44 let _ = adc.start();
45 let _ = adc2.start();
46 loop {
47 match adc.read_exact(&mut buffer1).await {
48 Ok(_data) => {
49 let toc = Instant::now();
50 info!(
51 "\n adc1: {} dt = {}, n = {}",
52 buffer1[0..16],
53 (toc - tic).as_micros(),
54 _data
55 );
56 tic = toc;
57 }
58 Err(e) => {
59 warn!("Error: {:?}", e);
60 buffer1 = [0u16; 512];
61 let _ = adc.start();
62 }
63 }
64
65 match adc2.read_exact(&mut buffer2).await {
66 Ok(_data) => {
67 let toc = Instant::now();
68 info!(
69 "\n adc2: {} dt = {}, n = {}",
70 buffer2[0..16],
71 (toc - tic).as_micros(),
72 _data
73 );
74 tic = toc;
75 }
76 Err(e) => {
77 warn!("Error: {:?}", e);
78 buffer2 = [0u16; 512];
79 let _ = adc2.start();
80 }
81 }
82 }
83}