#![no_std]
#![no_main]
use core::cell::{Cell, RefCell};
use cortex_m::peripheral::NVIC;
use cortex_m_rt::entry;
use critical_section::Mutex;
use defmt_rtt as _;
use panic_halt as _;
use gd32e2_hal::exti::{EdgeTrigger, ExtiLine};
use gd32e2_hal::gpio::{Output, Pin, PushPull};
use gd32e2_hal::pac::{self, interrupt};
use gd32e2_hal::prelude::*;
use gd32e2_hal::rcu::{ClockConfig, PllFreq, SysClk};
type Line = ExtiLine<0, Pin<'A', 0, Output<PushPull>>>;
static LINE: Mutex<RefCell<Option<Line>>> = Mutex::new(RefCell::new(None));
static COUNT: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
const SETTLE: u32 = 4_800;
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut fmc = dp.fmc.constrain();
let config = ClockConfig::default().sysclk(SysClk::Pll(PllFreq::Mhz48));
let mut rcu = dp.rcu.constrain().freeze(&mut fmc, config);
let mut syscfg = dp.syscfg.constrain(&mut rcu);
let gpioa = dp.gpioa.split(&mut rcu);
let pa0 = gpioa.pa0.into_push_pull_output();
let lines = dp.exti.split();
let mut line = lines.line0.source(&mut syscfg, pa0);
line.edge(EdgeTrigger::Rising);
line.listen();
critical_section::with(|cs| LINE.borrow(cs).replace(Some(line)));
unsafe { NVIC::unmask(pac::Interrupt::EXTI0_1) };
for round in 1..=3 {
toggle();
toggle();
defmt::info!("round {}: {} interrupts", round, count());
}
with_line(|line| line.edge(EdgeTrigger::None));
toggle();
defmt::info!("after a toggle with no edge selected: {}", count());
with_line(|line| line.pend());
cortex_m::asm::delay(SETTLE);
defmt::info!("after pend: {}", count());
with_line(|line| {
line.unlisten();
line.listen_event();
line.edge(EdgeTrigger::Rising);
});
toggle();
toggle();
let pending = with_line(|line| line.is_pending());
defmt::info!(
"event output: {} interrupts, PD {}",
count(),
if pending { "latched" } else { "clear" }
);
let line = critical_section::with(|cs| LINE.borrow(cs).take()).unwrap();
let (_line, mut pa0) = line.release();
pa0.set_low();
defmt::info!("done");
loop {
cortex_m::asm::wfi();
}
}
fn toggle() {
with_line(|line| line.pin_mut().toggle());
cortex_m::asm::delay(SETTLE);
}
fn with_line<R>(f: impl FnOnce(&mut Line) -> R) -> R {
critical_section::with(|cs| f(LINE.borrow(cs).borrow_mut().as_mut().unwrap()))
}
fn count() -> u32 {
critical_section::with(|cs| COUNT.borrow(cs).get())
}
#[interrupt]
fn EXTI0_1() {
critical_section::with(|cs| {
if let Some(line) = LINE.borrow(cs).borrow_mut().as_mut() {
if line.is_pending() {
line.clear_interrupt();
let count = COUNT.borrow(cs);
count.set(count.get() + 1);
}
}
});
}