diff --git a/boards/grand_central_m4/Cargo.toml b/boards/grand_central_m4/Cargo.toml index 80601184ea0f..978a2053b2d7 100644 --- a/boards/grand_central_m4/Cargo.toml +++ b/boards/grand_central_m4/Cargo.toml @@ -30,9 +30,17 @@ features = ["critical-section-single-core"] cortex-m = "0.7" usbd-serial = "0.2" panic-halt = "1.0.0" +panic-probe = "1.0.0" panic-semihosting = "0.6" smart-leds = "0.3" ws2812-timer-delay = "0.3" +embassy-executor = { version = "0.7.0", features = [ + "arch-cortex-m", + "executor-thread", + "task-arena-size-8192", +] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" [features] default = ["rt", "atsamd-hal/samd51p"] @@ -41,6 +49,7 @@ max-channels = ["dma", "atsamd-hal/max-channels"] rt = ["cortex-m-rt", "atsamd-hal/samd51p-rt"] usb = ["atsamd-hal/usb", "usb-device"] use_semihosting = [] +async = ["atsamd-hal/async"] # for cargo flash [package.metadata] @@ -62,3 +71,7 @@ name = "neopixel_rainbow" [[example]] name = "usb_serial" required-features = ["usb"] + +[[example]] +name = "async_dmac" +required-features = ["async", "dma"] diff --git a/boards/grand_central_m4/examples/async_dmac.rs b/boards/grand_central_m4/examples/async_dmac.rs new file mode 100644 index 000000000000..cedb3568f178 --- /dev/null +++ b/boards/grand_central_m4/examples/async_dmac.rs @@ -0,0 +1,74 @@ +//! This example shows a safe API to +//! execute a memory-to-memory DMA transfer + +#![no_std] +#![no_main] + +use defmt_rtt as _; +use panic_probe as _; + +use bsp::hal; +use bsp::pac; +use grand_central_m4 as bsp; +use hal::{ + clock::GenericClockController, + dmac::{DmaController, PriorityLevel, TriggerAction, TriggerSource}, +}; + +atsamd_hal::bind_multiple_interrupts!(struct Irqs { + DMAC: [DMAC_0, DMAC_1, DMAC_2, DMAC_OTHER] => atsamd_hal::dmac::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_s: embassy_executor::Spawner) { + let mut peripherals = pac::Peripherals::take().unwrap(); + let _core = pac::CorePeripherals::take().unwrap(); + + let _clocks = GenericClockController::with_external_32kosc( + peripherals.gclk, + &mut peripherals.mclk, + &mut peripherals.osc32kctrl, + &mut peripherals.oscctrl, + &mut peripherals.nvmctrl, + ); + + // Initialize DMA Controller + let dmac = DmaController::init(peripherals.dmac, &mut peripherals.pm); + + // Turn dmac into an async controller + let mut dmac = dmac.into_future(crate::Irqs); + // Get individual handles to DMA channels + let channels = dmac.split(); + + // Initialize DMA Channel 0 + let mut channel = channels.0.init(PriorityLevel::Lvl0); + + let mut source = [0xff; 100]; + let mut dest = [0x0; 100]; + + defmt::info!( + "Launching a DMA transfer.\n\tSource: {:#x}\n\tDestination: {:#x}", + &source, + &dest + ); + + channel + .transfer_future( + &mut source, + &mut dest, + TriggerSource::Disable, + TriggerAction::Block, + ) + .await + .unwrap(); + + defmt::info!( + "Finished DMA transfer.\n\tSource: {:#x}\n\tDestination: {:#x}", + &source, + &dest + ); + + loop { + cortex_m::asm::wfi(); + } +}