1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
//! This example shows how to use `zerocopy_channel` from `embassy_sync` for
//! sending large values between two tasks without copying.
//! The example also shows how to use the RP235x ADC with DMA.
#![no_std]
#![no_main]
use core::sync::atomic::{AtomicU16, Ordering};
use defmt::*;
use embassy_executor::Spawner;
use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler};
use embassy_rp::gpio::Pull;
use embassy_rp::peripherals::DMA_CH0;
use embassy_rp::{Peri, bind_interrupts};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender};
use embassy_time::{Duration, Ticker, Timer};
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};
type SampleBuffer = [u16; 512];
bind_interrupts!(struct Irqs {
ADC_IRQ_FIFO => InterruptHandler;
});
const BLOCK_SIZE: usize = 512;
const NUM_BLOCKS: usize = 2;
static MAX: AtomicU16 = AtomicU16::new(0);
struct AdcParts {
adc: Adc<'static, Async>,
pin: adc::Channel<'static>,
dma: Peri<'static, DMA_CH0>,
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
info!("Here we go!");
let adc_parts = AdcParts {
adc: Adc::new(p.ADC, Irqs, Config::default()),
pin: adc::Channel::new_pin(p.PIN_29, Pull::None),
dma: p.DMA_CH0,
};
static BUF: StaticCell<[SampleBuffer; NUM_BLOCKS]> = StaticCell::new();
let buf = BUF.init([[0; BLOCK_SIZE]; NUM_BLOCKS]);
static CHANNEL: StaticCell<Channel<'_, NoopRawMutex, SampleBuffer>> = StaticCell::new();
let channel = CHANNEL.init(Channel::new(buf));
let (sender, receiver) = channel.split();
spawner.spawn(consumer(receiver).unwrap());
spawner.spawn(producer(sender, adc_parts).unwrap());
let mut ticker = Ticker::every(Duration::from_secs(1));
loop {
ticker.next().await;
let max = MAX.load(Ordering::Relaxed);
info!("latest block's max value: {:?}", max);
}
}
#[embassy_executor::task]
async fn producer(mut sender: Sender<'static, NoopRawMutex, SampleBuffer>, mut adc: AdcParts) {
loop {
// Obtain a free buffer from the channel
let buf = sender.send().await;
// Fill it with data
adc.adc
.read_many(&mut adc.pin, buf, 1, adc.dma.reborrow())
.await
.unwrap();
// Notify the channel that the buffer is now ready to be received
sender.send_done();
}
}
#[embassy_executor::task]
async fn consumer(mut receiver: Receiver<'static, NoopRawMutex, SampleBuffer>) {
loop {
// Receive a buffer from the channel
let buf = receiver.receive().await;
// Simulate using the data, while the producer is filling up the next buffer
Timer::after_micros(1000).await;
let max = buf.iter().max().unwrap();
MAX.store(*max, Ordering::Relaxed);
// Notify the channel that the buffer is now ready to be reused
receiver.receive_done();
}
}
|