diff --git a/.vscode/launch.json b/.vscode/launch.json index 294073f9d79def05bd65af060231b456d5e1c897..e015a23e07b9dd0e06c531e4eeb7f58770f1b6e6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -57,6 +57,81 @@ }, "cwd": "${workspaceRoot}", }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "stop", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/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", + "servertype": "openocd", + "name": "sleep", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/sleep", + "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", + "servertype": "openocd", + "name": "sleep (release)", + "executable": "./target/thumbv7em-none-eabihf/release/examples/sleep", + "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", diff --git a/examples/sleep.rs b/examples/sleep.rs index 14175cb00cbb82279cc2fbe2f738749b951ad646..83e214e9cb7c70b87d60d80b136ace628bfd2eb3 100644 --- a/examples/sleep.rs +++ b/examples/sleep.rs @@ -50,26 +50,6 @@ fn dbg_disable() { }); } -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 @@ -90,45 +70,63 @@ fn main() -> ! { r.EXTI.ftsr.modify(|_, w| w.tr1().set_bit()); asm::bkpt(); - blink(&r, &p); + 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::bkpt(); + 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! } - // asm::bkpt(); - loop {} } +// 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 // bind the EXTI1 handler interrupt!(EXTI1, exti1); // unsafe version where we access GPIOA through the (raw) pointer -fn blink2() { +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 {} + for _ in 0..1000 { + asm::nop(); + } // wait_cycles(p, 1000_000); GPIOA.bsrr.write(|w| w.bs5().set_bit()); - for _ in 0..1000 {} + for _ in 0..1000 { + asm::nop(); + } // wait_cycles(p, 1000_000); } GPIOA.moder.modify(|_, w| w.moder5().input_mode()); + RCC.ahb1enr.modify(|_, w| w.gpioaen().clear_bit()); } -use cortex_m::interrupt::Nr; // the exti1 interrupt implementation fn exti1() { - // dbg_enable(); - // asm::bkpt(); - blink2(); // it will take some time so bounces are likely gone + blink(); // it will take some time so bounces are likely gone // // let's try to "fake" access to GPIOA // // let g = stm32f40x::GPIOA {