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