From aafc925231e98e9c1fe5fd33ea4705bf84f30522 Mon Sep 17 00:00:00 2001 From: dcz Date: Sat, 20 Sep 2025 13:53:35 +0200 Subject: [PATCH 1/2] example: Explain clearing interrupt flags --- examples/interrupt.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/interrupt.rs b/examples/interrupt.rs index d39bf34..375f8ec 100644 --- a/examples/interrupt.rs +++ b/examples/interrupt.rs @@ -59,6 +59,7 @@ fn main() -> ! { fn TIMER1() { unsafe { if let Some(timer1) = G_TIMER1.as_mut() { + // If the interrupt flag is not cleared, the interrupt will get issued again immediately. timer1.clear_update_interrupt_flag(); } if let Some(led) = R_LED.as_mut() { @@ -69,4 +70,4 @@ fn TIMER1() { } } } -} \ No newline at end of file +} From f6872e6a790eebd1b040657746af9ceef5d9d712 Mon Sep 17 00:00:00 2001 From: dcz Date: Sat, 20 Sep 2025 14:23:52 +0200 Subject: [PATCH 2/2] examples: Add exti pin interrupt --- Cargo.toml | 3 +- examples/interrupt_pin.rs | 88 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 examples/interrupt_pin.rs diff --git a/Cargo.toml b/Cargo.toml index 6500fd0..c7f5634 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,11 +18,12 @@ default-target = "x86_64-unknown-linux-gnu" gd32vf103xx-hal = "0.5.0" embedded-hal = "0.2.6" nb = "1.0.0" -riscv = "0.10.1" +riscv = {version = "0.10.1", features = ["critical-section-single-hart"]} st7735-lcd = { version = "0.8.1", optional = true } embedded-sdmmc = { version = "0.3.0", optional = true } [dev-dependencies] +critical-section = "1.2" riscv-rt = "0.11.0" panic-halt = "0.2.0" embedded-graphics = "0.7.1" diff --git a/examples/interrupt_pin.rs b/examples/interrupt_pin.rs new file mode 100644 index 0000000..6010211 --- /dev/null +++ b/examples/interrupt_pin.rs @@ -0,0 +1,88 @@ +/*! This example demonstrates how to interrupt on pin state change. + +The LED will toggle every time the PB9 pin is shorted (without debouncing). +*/ + +#![no_std] +#![no_main] +use core::cell::RefCell; +use critical_section::{self, Mutex}; +use gd32vf103xx_hal::{exti::{Exti, ExtiLine, TriggerEdge}, pac::Interrupt}; +use panic_halt as _; +use longan_nano::hal::{pac, prelude::*, pac::*, eclic::*}; +use longan_nano::led::{rgb, Led, RED}; +use riscv_rt::entry; + +static R_LED: Mutex>> = Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let dp = pac::Peripherals::take().unwrap(); + let mut rcu = dp + .RCU + .configure() + .ext_hf_clock(8.mhz()) + .sysclk(108.mhz()) + .freeze(); + + let gpioa = dp.GPIOA.split(&mut rcu); + let gpiob = dp.GPIOB.split(&mut rcu); + let gpioc = dp.GPIOC.split(&mut rcu); + + let (mut red, mut green, mut blue) = rgb(gpioc.pc13, gpioa.pa1, gpioa.pa2); + red.off(); + green.off(); + blue.off(); + + critical_section::with(|cs| + R_LED.borrow(cs).replace(Some(red)) + ); + + // Make sure the pin is high when not shorted. A floating pin would keep flipping. + let butb8 = gpiob.pb8.into_pull_up_input(); + + // Configure external interrupts which feed into the interrupt controller + let mut exti = Exti::new(dp.EXTI); + let extiline = ExtiLine::from_gpio_line(butb8.pin_number()).unwrap(); + exti.listen(extiline, TriggerEdge::Falling); + + // Connect the pin to the external interrupt line + let mut afio = dp.AFIO.constrain(&mut rcu); + afio.extiss(gd32vf103xx_hal::gpio::Port::PBx, 8); + + // Configure the interrupt controller + ECLIC::reset(); + ECLIC::set_threshold_level(Level::L0); + ECLIC::set_level_priority_bits(LevelPriorityBits::L3P1); + ECLIC::setup( + Interrupt::EXTI_LINE9_5, + gd32vf103xx_hal::eclic::TriggerType::FallingEdge, + gd32vf103xx_hal::eclic::Level::L1, + gd32vf103xx_hal::eclic::Priority::P1, + ); + + unsafe { + ECLIC::unmask(Interrupt::EXTI_LINE9_5); + riscv::interrupt::enable(); + }; + + loop { } +} + +/// The interrupt handler. +#[allow(non_snake_case)] +#[no_mangle] +fn EXTI_LINE9_5() { + // This handler is responsible for EXTI interrupt lines 5 to 9, but this example uses only one line, so there's no need to check which one has been triggered. + Exti::clear(ExtiLine::from_gpio_line(8).unwrap()); + + critical_section::with(|cs| { + if let Some(led) = R_LED.borrow(cs).borrow_mut().as_mut() { + if led.is_on() { + led.off(); + } else { + led.on(); + } + } + }) +}