-
Notifications
You must be signed in to change notification settings - Fork 203
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(atsamd-hal-macros): Add MSRV to atsamd-hal-macros
Suppresses clippy lints for unsupported APIs in the standard library
- Loading branch information
1 parent
36fc84c
commit 0da028e
Showing
2 changed files
with
113 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Pin<PA18, PullUpInterrupt>, 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<RefCell<Option<ButtonPin>>> = 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); | ||
} |