From 0db730af6495060da7c5b6d165d73a1c3a287069 Mon Sep 17 00:00:00 2001 From: Per <Per Lindgren> Date: Wed, 6 Jun 2018 00:47:03 +0200 Subject: [PATCH] sleep mode --- examples/sleep.rs | 157 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 examples/sleep.rs diff --git a/examples/sleep.rs b/examples/sleep.rs new file mode 100644 index 0000000..fda1df1 --- /dev/null +++ b/examples/sleep.rs @@ -0,0 +1,157 @@ +//! Sleep mode example + +#![no_main] +#![no_std] + +extern crate cortex_m; + +#[macro_use(interrupt)] +extern crate stm32f40x; +use stm32f40x::Interrupt; + +#[macro_use(entry, exception)] +extern crate cortex_m_rt as rt; + +extern crate panic_abort; +use cortex_m::asm; +use rt::ExceptionFrame; + +use cortex_m::peripheral::Peripherals; + +// set the MCU in debug sleepdeep mode on WFI/WFE +// debugging is possible even if sleeping +fn dbg_enable() { + let dbg = unsafe { &*stm32f40x::DBG::ptr() }; + dbg.dbgmcu_cr.modify(|_, w| { + w.dbg_sleep() + .set_bit() + .dbg_stop() + .set_bit() + .dbg_standby() + .set_bit() + .trace_ioen() + .set_bit() + }); +} + +// set the MCU in true sleepdeep mode on WFI/WFE +// debugging is disabled (until re-enabled) +fn dbg_disable() { + let dbg = unsafe { &*stm32f40x::DBG::ptr() }; + dbg.dbgmcu_cr.modify(|_, w| { + w.dbg_sleep() + .clear_bit() + .dbg_stop() + .clear_bit() + .dbg_standby() + .clear_bit() + .trace_ioen() + .clear_bit() + }); +} + +fn wait_cycles(p: &Peripherals, nr_cycles: u32) { + let t = p.DWT.cyccnt.read().wrapping_add(nr_cycles); + while (p.DWT.cyccnt.read().wrapping_sub(t) as i32) < 0 {} +} + +fn blink(r: &stm32f40x::Peripherals, p: &Peripherals) { + r.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); + r.GPIOA.moder.modify(|_, w| w.moder5().output_mode()); + for _ in 0..10 { + r.GPIOA.bsrr.write(|w| w.br5().set_bit()); + for _ in 0..1000 {} + // wait_cycles(p, 1000_000); + + r.GPIOA.bsrr.write(|w| w.bs5().set_bit()); + for _ in 0..1000 {} + // wait_cycles(p, 1000_000); + } + r.GPIOA.moder.modify(|_, w| w.moder5().input_mode()); +} + +// the program entry point is ... +entry!(main); +// ... this never ending function +fn main() -> ! { + let r = stm32f40x::Peripherals::take().unwrap(); + let mut p = Peripherals::take().unwrap(); + + // enable the EXTI1 interrupt + p.NVIC.enable(Interrupt::EXTI1); + // enable gpioa (input mode on reset) + r.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); + // enbable masking of EXTI line 1 + r.EXTI.imr.modify(|_, w| w.mr1().set_bit()); + // trigger on falling edge + r.EXTI.ftsr.modify(|_, w| w.tr1().set_bit()); + + asm::bkpt(); + blink(&r, &p); + + // p.NVIC.set_pending(Interrupt::EXTI1); + + dbg_disable(); + asm::wfi(); + dbg_enable(); + // asm::bkpt(); + loop {} +} + +// bind the EXTI1 handler +interrupt!(EXTI1, exti1); + +// unsafe version where we access GPIOA through the (raw) pointer +fn blink2() { + let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() }; + GPIOA.moder.modify(|_, w| w.moder5().output_mode()); + for _ in 0..10 { + GPIOA.bsrr.write(|w| w.br5().set_bit()); + for _ in 0..1000 {} + // wait_cycles(p, 1000_000); + + GPIOA.bsrr.write(|w| w.bs5().set_bit()); + for _ in 0..1000 {} + // wait_cycles(p, 1000_000); + } + GPIOA.moder.modify(|_, w| w.moder5().input_mode()); +} + +use cortex_m::interrupt::Nr; +// the exti1 interrupt implementation +fn exti1() { + // dbg_enable(); + // asm::bkpt(); + blink2(); + + // // let's try to "fake" access to GPIOA + // // let g = stm32f40x::GPIOA { + // // _marker: core::marker::PhantomData, <- the field is private, so we cannot + // // }; + // asm::bkpt(); + + // clear pending state + let exti = unsafe { &*stm32f40x::EXTI::ptr() }; + exti.imr.modify(|_, w| w.mr1().clear_bit()); + exti.pr.reset(); + + let nvic = unsafe { &*cortex_m::peripheral::NVIC::ptr() }; + let nr = Interrupt::EXTI1.nr(); + unsafe { nvic.icpr[usize::from(nr / 32)].write(1 << (nr % 32)) }; + unsafe { nvic.icer[usize::from(nr / 32)].write(1 << (nr % 32)) }; +} + +// define the hard fault handler +exception!(HardFault, hard_fault); + +fn hard_fault(_ef: &ExceptionFrame) -> ! { + asm::bkpt(); + loop {} +} + +// define the default exception handler +exception!(*, default_handler); + +fn default_handler(_irqn: i16) { + asm::bkpt(); +} -- GitLab