aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32f4
diff options
context:
space:
mode:
authorseth <[email protected]>2024-06-24 17:09:43 -0700
committerseth <[email protected]>2024-06-24 17:09:43 -0700
commitf64dd8228b7b8a570546ffa9b522ae85145cfdef (patch)
tree37a5d6b42c8488dfbb53b5522e634fd20ac02dbb /examples/stm32f4
parentab3cc7226a5107111287899297f1f67ff9e1ee82 (diff)
new PR, taking Dirbao's advice to make the DMA impl in a separate struct that consumes Adc<T> to make RingBufferedAdc<T>. Handling overrun similar to RingBufferedUart
Diffstat (limited to 'examples/stm32f4')
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs59
1 files changed, 59 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..a2611bb6f
--- /dev/null
+++ b/examples/stm32f4/src/bin/adc_dma.rs
@@ -0,0 +1,59 @@
1#![no_std]
2#![no_main]
3use cortex_m::singleton;
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::adc::RingBufferedAdc;
7use embassy_stm32::adc::{Adc, SampleTime, Sequence};
8use embassy_time::{Instant, Timer};
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 const ADC_BUF_SIZE: usize = 1024;
14 let mut p = embassy_stm32::init(Default::default());
15
16 let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap();
17
18 let adc = Adc::new(p.ADC1);
19
20 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(p.DMA2_CH0, adc_data);
21
22 adc.set_sample_sequence(Sequence::One, &mut p.PA0, SampleTime::CYCLES112);
23 adc.set_sample_sequence(Sequence::Two, &mut p.PA2, SampleTime::CYCLES112);
24 adc.set_sample_sequence(Sequence::Three, &mut p.PA1, SampleTime::CYCLES112);
25 adc.set_sample_sequence(Sequence::Four, &mut p.PA3, SampleTime::CYCLES112);
26
27 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around
28 // 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
29 // 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
30 // a reduction of performance as each time the buffer is reset, the adc & dma buffer must be restarted.
31
32 // 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
33 // frequently.
34 let mut tic = Instant::now();
35 let mut buffer1: [u16; 256] = [0u16; 256];
36 let _ = adc.start();
37 loop {
38 match adc.read(&mut buffer1).await {
39 Ok(_data) => {
40 let toc = Instant::now();
41 info!(
42 "\n adc1: {} dt = {}, n = {}",
43 buffer1[0..16],
44 (toc - tic).as_micros(),
45 _data
46 );
47 tic = toc;
48 }
49 Err(e) => {
50 warn!("Error: {:?}", e);
51 buffer1 = [0u16; 256];
52 let _ = adc.start();
53 continue;
54 }
55 }
56
57 Timer::after_micros(300).await;
58 }
59}