mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 00:02:28 +00:00
Merge pull request #3037 from kalkyl/zerocopy
rp: Add zerocopy channel example
This commit is contained in:
commit
5f9bc6def7
94
examples/rp/src/bin/zerocopy.rs
Normal file
94
examples/rp/src/bin/zerocopy.rs
Normal file
@ -0,0 +1,94 @@
|
||||
//! 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 RP2040 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::bind_interrupts;
|
||||
use embassy_rp::gpio::Pull;
|
||||
use embassy_rp::peripherals::DMA_CH0;
|
||||
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: 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.must_spawn(consumer(receiver));
|
||||
spawner.must_spawn(producer(sender, adc_parts));
|
||||
|
||||
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, &mut adc.dma).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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user