From 03d8f99aa57d71c27745972f2bcd9ba3450bd8c3 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Tue, 4 Jun 2024 00:38:51 +0200 Subject: [PATCH 1/3] rp: Add zerocopy channel example --- examples/rp/src/bin/zerocopy.rs | 90 +++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 examples/rp/src/bin/zerocopy.rs diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs new file mode 100644 index 000000000..b5bd11512 --- /dev/null +++ b/examples/rp/src/bin/zerocopy.rs @@ -0,0 +1,90 @@ +#![no_std] +#![no_main] + +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 portable_atomic::{AtomicU16, Ordering}; +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> = 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(); + } +} From 874d5f7c65f2af21e4666bf92800d304c2d9e01d Mon Sep 17 00:00:00 2001 From: kalkyl Date: Tue, 4 Jun 2024 00:53:51 +0200 Subject: [PATCH 2/3] core atomic --- examples/rp/src/bin/zerocopy.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs index b5bd11512..730a3ae0c 100644 --- a/examples/rp/src/bin/zerocopy.rs +++ b/examples/rp/src/bin/zerocopy.rs @@ -1,6 +1,8 @@ #![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}; @@ -10,7 +12,6 @@ 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 portable_atomic::{AtomicU16, Ordering}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; From f9d8c68fc8ed490e72e61b74d2b3b26bbbd0434c Mon Sep 17 00:00:00 2001 From: kalkyl Date: Tue, 4 Jun 2024 01:20:19 +0200 Subject: [PATCH 3/3] Add description --- examples/rp/src/bin/zerocopy.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs index 730a3ae0c..39f03c8e4 100644 --- a/examples/rp/src/bin/zerocopy.rs +++ b/examples/rp/src/bin/zerocopy.rs @@ -1,3 +1,6 @@ +//! 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]