Skip to content
Snippets Groups Projects
Commit 809b11df authored by Per's avatar Per
Browse files

sleep stop

parent ddad6726
No related branches found
No related tags found
No related merge requests found
......@@ -107,6 +107,31 @@
},
"cwd": "${workspaceRoot}"
},
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"name": "sleep_stop",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/sleep_stop",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"swoConfig": {
"enabled": true,
"cpuFrequency": 8000000,
"swoFrequency": 2000000, // you may try 1000000 if not working
"source": "probe",
"decoders": [
{
"type": "console",
"label": "Name",
"port": 0
}
]
},
"cwd": "${workspaceRoot}"
},
{
"type": "cortex-debug",
"request": "launch",
......
//! 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() };
#[allow(non_snake_case)]
let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() };
#[allow(non_snake_case)]
let GPIOB = unsafe { &*stm32f40x::GPIOB::ptr() };
dbg.dbgmcu_cr.modify(|_, w| {
w.dbg_sleep()
.set_bit()
.dbg_stop()
.set_bit()
.dbg_standby()
.set_bit()
.trace_ioen()
.set_bit()
});
// GPIOB.moder.reset();
// GPIOA.moder.reset();
// GPIOB.pupdr.reset();
// GPIOA.pupdr.reset();
}
// set the MCU in true sleepdeep mode on WFI/WFE
// debugging is disabled (until re-enabled)
fn dbg_disable() {
#[allow(non_snake_case)]
let DBG = unsafe { &*stm32f40x::DBG::ptr() };
#[allow(non_snake_case)]
let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() };
#[allow(non_snake_case)]
let GPIOB = unsafe { &*stm32f40x::GPIOB::ptr() };
asm::nop();
DBG.dbgmcu_cr.modify(|_, w| {
w.dbg_sleep()
.clear_bit()
.dbg_stop()
.clear_bit()
.dbg_standby()
.clear_bit()
.trace_ioen()
.clear_bit()
});
// set all gpio to analog input
// let _a_moder_ = GPIOA.moder.read().bits();
// let _b_moder_ = GPIOB.moder.read().bits();
// let _a_pupdr_ = GPIOA.pupdr.read().bits();
// let _b_pupdr_ = GPIOB.pupdr.read().bits();
// GPIOB.moder.write(|w| unsafe { w.bits(0) });
// GPIOA.moder.write(|w| unsafe { w.bits(0) });
// GPIOB.pupdr.write(|w| unsafe { w.bits(0) });
// GPIOA.pupdr.write(|w| unsafe { w.bits(0) });
// let _a_moder = GPIOA.moder.read().bits();
// let _b_moder = GPIOB.moder.read().bits();
// let _a_pupdr = GPIOA.pupdr.read().bits();
// let _b_pupdr = GPIOB.pupdr.read().bits();
asm::nop();
}
// 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().gpioben().set_bit());
let mut read: u32 = 0;
r.GPIOA.pupdr.modify(|r, w| {
read = r.bits();
w.pupdr1().pull_up()
});
#[allow(non_snake_case)]
let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() };
asm::nop();
// SYSCFG.exti1 is PAx (0000) by reset
// 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();
p.SCB.set_sleepdeep();
// enable pwr
r.RCC.apb1enr.modify(|_, w| w.pwren().set_bit());
// set standby mode
// r.PWR
// .cr
// .write(|w| unsafe { w.bits((1 << 10) | 0x0000_8000) });
r.PWR
.cr
.modify(|_, w| w.pdds().clear_bit().lpds().set_bit().fpds().set_bit());
// r.PWR
// .cr
// .modify(|_, w| w.pdds().clear_bit().lpds().clear_bit());
blink();
// p.NVIC.set_pending(Interrupt::EXTI1);
loop {
asm::nop(); // put gdb breakpoint here, the MCU and gdb will detect breakpoint
dbg_disable();
asm::wfi();
dbg_enable();
asm::nop(); // put gdb breakpoint here, in debug mode its caught twice
// first occation (on wakeup), gdb does NOT report span correctly,
// second occation, gdb DEOS report span correctly
asm::bkpt(); // here the MCU halt, and gdb detects the asm breakpoint
// gdb continue, will catch the gdb breakpoint at "dbg_disable"
// this is good as it shows that disabling and re-enabling gdb debugging works
// even if the gdb communictation has been disrputed and re-estabished, nice!
}
}
// the dbg_sleep, and dbg_stop both set deos not prohibit sleep mode debugging (error?)
// the bdg_standby set further reduces power, and prohibits debugging
// the behavior seems not to comply with the documentation
// as expected debugging release code puts the gdb breakpoint at the wrong position
// as expected the initial breakpoint after wakeup deos not register in gdb correctly
// also the blink loop becomes to fast to observe
// unsafe version where we access GPIOA through the (raw) pointer
fn blink() {
#[allow(non_snake_case)]
let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() };
// #[allow(non_snake_case)]
// let RCC = unsafe { &*stm32f40x::RCC::ptr() };
// RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
GPIOA.moder.modify(|_, w| w.moder5().output_mode());
for _ in 0..10 {
GPIOA.bsrr.write(|w| w.br5().set_bit());
for _ in 0..1000 {
asm::nop();
}
GPIOA.bsrr.write(|w| w.bs5().set_bit());
for _ in 0..1000 {
asm::nop();
}
}
GPIOA.moder.modify(|_, w| w.moder5().input_mode());
// RCC.ahb1enr.modify(|_, w| w.gpioaen().clear_bit());
}
// bind the EXTI1 handler
interrupt!(EXTI1, exti1);
// the exti1 interrupt implementation
fn exti1() {
blink(); // it will take some time so bounces are likely gone
// // 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.pr.write(|w| w.pr1().set_bit());
}
// 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();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment