diff options
| author | kalkyl <[email protected]> | 2024-06-04 00:38:51 +0200 |
|---|---|---|
| committer | kalkyl <[email protected]> | 2024-06-04 00:38:51 +0200 |
| commit | 03d8f99aa57d71c27745972f2bcd9ba3450bd8c3 (patch) | |
| tree | 23c58259b87bd7958af682321b98035f22518335 /examples/rp/src/bin/zerocopy.rs | |
| parent | 9856d216939d9433e840289966e313c9aa377fca (diff) | |
rp: Add zerocopy channel example
Diffstat (limited to 'examples/rp/src/bin/zerocopy.rs')
| -rw-r--r-- | examples/rp/src/bin/zerocopy.rs | 90 |
1 files changed, 90 insertions, 0 deletions
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 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; | ||
| 7 | use embassy_rp::bind_interrupts; | ||
| 8 | use embassy_rp::gpio::Pull; | ||
| 9 | use embassy_rp::peripherals::DMA_CH0; | ||
| 10 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 11 | use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; | ||
| 12 | use embassy_time::{Duration, Ticker, Timer}; | ||
| 13 | use portable_atomic::{AtomicU16, Ordering}; | ||
| 14 | use static_cell::StaticCell; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | ||
| 16 | |||
| 17 | type SampleBuffer = [u16; 512]; | ||
| 18 | |||
| 19 | bind_interrupts!(struct Irqs { | ||
| 20 | ADC_IRQ_FIFO => InterruptHandler; | ||
| 21 | }); | ||
| 22 | |||
| 23 | const BLOCK_SIZE: usize = 512; | ||
| 24 | const NUM_BLOCKS: usize = 2; | ||
| 25 | static MAX: AtomicU16 = AtomicU16::new(0); | ||
| 26 | |||
| 27 | struct AdcParts { | ||
| 28 | adc: Adc<'static, Async>, | ||
| 29 | pin: adc::Channel<'static>, | ||
| 30 | dma: DMA_CH0, | ||
| 31 | } | ||
| 32 | |||
| 33 | #[embassy_executor::main] | ||
| 34 | async fn main(spawner: Spawner) { | ||
| 35 | let p = embassy_rp::init(Default::default()); | ||
| 36 | info!("Here we go!"); | ||
| 37 | |||
| 38 | let adc_parts = AdcParts { | ||
| 39 | adc: Adc::new(p.ADC, Irqs, Config::default()), | ||
| 40 | pin: adc::Channel::new_pin(p.PIN_29, Pull::None), | ||
| 41 | dma: p.DMA_CH0, | ||
| 42 | }; | ||
| 43 | |||
| 44 | static BUF: StaticCell<[SampleBuffer; NUM_BLOCKS]> = StaticCell::new(); | ||
| 45 | let buf = BUF.init([[0; BLOCK_SIZE]; NUM_BLOCKS]); | ||
| 46 | |||
| 47 | static CHANNEL: StaticCell<Channel<'_, NoopRawMutex, SampleBuffer>> = StaticCell::new(); | ||
| 48 | let channel = CHANNEL.init(Channel::new(buf)); | ||
| 49 | let (sender, receiver) = channel.split(); | ||
| 50 | |||
| 51 | spawner.must_spawn(consumer(receiver)); | ||
| 52 | spawner.must_spawn(producer(sender, adc_parts)); | ||
| 53 | |||
| 54 | let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 55 | loop { | ||
| 56 | ticker.next().await; | ||
| 57 | let max = MAX.load(Ordering::Relaxed); | ||
| 58 | info!("latest block's max value: {:?}", max); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | #[embassy_executor::task] | ||
| 63 | async fn producer(mut sender: Sender<'static, NoopRawMutex, SampleBuffer>, mut adc: AdcParts) { | ||
| 64 | loop { | ||
| 65 | // Obtain a free buffer from the channel | ||
| 66 | let buf = sender.send().await; | ||
| 67 | |||
| 68 | // Fill it with data | ||
| 69 | adc.adc.read_many(&mut adc.pin, buf, 1, &mut adc.dma).await.unwrap(); | ||
| 70 | |||
| 71 | // Notify the channel that the buffer is now ready to be received | ||
| 72 | sender.send_done(); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | #[embassy_executor::task] | ||
| 77 | async fn consumer(mut receiver: Receiver<'static, NoopRawMutex, SampleBuffer>) { | ||
| 78 | loop { | ||
| 79 | // Receive a buffer from the channel | ||
| 80 | let buf = receiver.receive().await; | ||
| 81 | |||
| 82 | // Simulate using the data, while the producer is filling up the next buffer | ||
| 83 | Timer::after_micros(1000).await; | ||
| 84 | let max = buf.iter().max().unwrap(); | ||
| 85 | MAX.store(*max, Ordering::Relaxed); | ||
| 86 | |||
| 87 | // Notify the channel that the buffer is now ready to be reused | ||
| 88 | receiver.receive_done(); | ||
| 89 | } | ||
| 90 | } | ||
