From 0da028e193a36312d9b712def5962f18e6d7bb27 Mon Sep 17 00:00:00 2001 From: Justin Beaurivage Date: Wed, 4 Dec 2024 13:21:26 -0500 Subject: [PATCH] chore(atsamd-hal-macros): Add MSRV to atsamd-hal-macros Suppresses clippy lints for unsupported APIs in the standard library --- atsamd-hal-macros/Cargo.toml | 1 + boards/feather_m0/examples/eic2.rs | 112 +++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 boards/feather_m0/examples/eic2.rs diff --git a/atsamd-hal-macros/Cargo.toml b/atsamd-hal-macros/Cargo.toml index d1b9b4c6a12..6cba419b6f0 100644 --- a/atsamd-hal-macros/Cargo.toml +++ b/atsamd-hal-macros/Cargo.toml @@ -1,6 +1,7 @@ [package] authors = ["Tethys Svensson"] name = "atsamd-hal-macros" +rust-version = "1.77.2" version = "0.2.2" edition = "2021" license = "MIT OR Apache-2.0" diff --git a/boards/feather_m0/examples/eic2.rs b/boards/feather_m0/examples/eic2.rs new file mode 100644 index 00000000000..d580e6b0cc5 --- /dev/null +++ b/boards/feather_m0/examples/eic2.rs @@ -0,0 +1,112 @@ +#![no_std] +#![no_main] + +use panic_halt as _; + +use feather_m0 as bsp; + +use bsp::{entry, hal, pac}; + +use pac::{interrupt, CorePeripherals, Peripherals}; + +use core::cell::RefCell; +use core::sync::atomic::{AtomicBool, Ordering}; + +use bsp::hal::ehal::digital::StatefulOutputPin; +use cortex_m::{interrupt::Mutex, peripheral::NVIC}; + +use hal::{ + clock::GenericClockController, + eic::{Ch2, Eic, ExtInt, Sense}, + gpio::{Pin, PullUpInterrupt, PA18}, +}; + +type ButtonPin = ExtInt, Ch2>; + +// To avoid unsafely passing the button pin to the interrupt handler, +// we must use a Mutex. This can also be done safely by using a framework +// like RTIC. +static BUTTON_PIN: Mutex>> = Mutex::new(RefCell::new(None)); + +// Used to signal to the main thread that the interrupt has fired +// from the interrupt handler +static INTERRUPT_FIRED: AtomicBool = AtomicBool::new(false); + +#[embassy_executor::main] +async fn main() { + // -- Setup clocks and peripherals + let mut peripherals = Peripherals::take().unwrap(); + let mut core = CorePeripherals::take().unwrap(); + let mut clocks = GenericClockController::with_external_32kosc( + peripherals.gclk, + &mut peripherals.pm, + &mut peripherals.sysctrl, + &mut peripherals.nvmctrl, + ); + let gclk0 = clocks.gclk0(); + let pins = bsp::Pins::new(peripherals.port); + + // Take the LED pin and set it to output mode + let mut red_led: bsp::RedLed = pins.d13.into(); + + // Setup the external interrupt controller + let eic_clock = clocks.eic(&gclk0).unwrap(); + // Split the controller into its individual channels + let eic_channels = Eic::new(&mut peripherals.pm, eic_clock, peripherals.eic).split(); + + // Enable EIC interrupt in the NVIC + unsafe { + core.NVIC.set_priority(interrupt::EIC, 1); + NVIC::unmask(interrupt::EIC); + } + + // Take the user button pin + let button: Pin<_, PullUpInterrupt> = pins.d10.into(); + // Turn the pin into an ExtInt using EIC channel 2 + let mut extint = eic_channels.2.with_pin(button); + + // Setup the button pin to wake the CPU upon interrupt + extint.enable_interrupt_wake(); + + // Setup the pin to sense falling edges. It will generate + // interrupts on every falling edge, not juste the first one + extint.sense(Sense::Fall); + + // Enable the pin's interrupt + extint.enable_interrupt(); + + // Store the button pin in static storage so that the interrupt + // handler can access it + cortex_m::interrupt::free(|cs| BUTTON_PIN.borrow(cs).borrow_mut().replace(extint)); + + loop { + // Check if our interrupt has fired + if INTERRUPT_FIRED.load(Ordering::Acquire) { + // Toggle the LED! We don't use the return + // value, because toggling a pin is infaillible + // in atsamd-hal. + let _ = red_led.toggle(); + + // Reset the signal for the next loop + INTERRUPT_FIRED.store(false, Ordering::Release); + } + // Put the CPU to sleep while we wait for an interrupt + // to happen + cortex_m::asm::wfi(); + } +} + +/// The external interrupt controller handler +#[interrupt] +fn EIC() { + // Clear the interrupt so we don't reenter the handler + // infinitely + cortex_m::interrupt::free(|cs| { + let mut button = BUTTON_PIN.borrow(cs).borrow_mut(); + let button = button.as_mut().unwrap(); + button.clear_interrupt(); + }); + + // Send a signal to the main thread + INTERRUPT_FIRED.store(true, Ordering::Release); +}