From 9474be3d7ef14844aa3fd2732a75a278084512ba Mon Sep 17 00:00:00 2001 From: Per <Per Lindgren> Date: Thu, 28 Jun 2018 10:58:58 +0200 Subject: [PATCH] 14uA stop mode --- .cargo/config | 2 +- .vscode/launch.json | 193 +-------------- Cargo.toml | 9 +- examples/sleep_stop.rs | 537 ++++++++++++++++++++++++++++------------- memory.x | 4 +- stm32f1x_per.cfg | 80 ++++++ 6 files changed, 470 insertions(+), 355 deletions(-) create mode 100644 stm32f1x_per.cfg diff --git a/.cargo/config b/.cargo/config index 4847ccc..6f42214 100644 --- a/.cargo/config +++ b/.cargo/config @@ -49,4 +49,4 @@ rustflags = [ [build] # (a) you also need to comment out the other two `link-arg` lines. But note that as of v0.6.0 LLD # has a bug where it mislinks FFI calls and they up crashing the program at runtime[build] -target = "thumbv7em-none-eabihf" +target = "thumbv7m-none-eabi" diff --git a/.vscode/launch.json b/.vscode/launch.json index 01a0f4b..2c63a8b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,143 +4,15 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "type": "cortex-debug", - "request": "launch", - "servertype": "openocd", - "name": "hello", - "executable": "./target/thumbv7em-none-eabihf/debug/examples/hello", - "configFiles": [ - "interface/stlink.cfg", - "target/stm32f4x.cfg" - ], - "swoConfig": { - "enabled": true, - "cpuFrequency": 16000000, - "swoFrequency": 2000000, // you may try 1000000 if not working - "source": "probe", - "decoders": [ - { - "type": "console", - "label": "Name", - "port": 0 - } - ], - }, - "postLaunchCommands": [ - "monitor arm semihosting enable", - ], - "cwd": "${workspaceRoot}", - }, - { - "type": "cortex-debug", - "request": "launch", - "servertype": "openocd", - "name": "hello (release)", - "executable": "./target/thumbv7em-none-eabihf/release/examples/hello", - "configFiles": [ - "interface/stlink.cfg", - "target/stm32f4x.cfg" - ], - "swoConfig": { - "enabled": true, - "cpuFrequency": 16000000, - "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": "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_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", - "servertype": "openocd", - "name": "sleep (release)", - "executable": "./target/thumbv7em-none-eabihf/release/examples/sleep", + "executable": "./target/thumbv7m-none-eabi/debug/examples/sleep_stop", "configFiles": [ "interface/stlink.cfg", - "target/stm32f4x.cfg" + "target/stm32f1x.cfg" ], "swoConfig": { "enabled": true, @@ -153,32 +25,7 @@ "label": "Name", "port": 0 } - ] - }, - "cwd": "${workspaceRoot}" - }, - { - "type": "cortex-debug", - "request": "launch", - "servertype": "openocd", - "name": "standby", - "executable": "./target/thumbv7em-none-eabihf/debug/examples/standby", - "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}" }, @@ -186,11 +33,11 @@ "type": "cortex-debug", "request": "launch", "servertype": "openocd", - "name": "standby (release)", - "executable": "./target/thumbv7em-none-eabihf/release/examples/standby", + "name": "sleep_stop (stm32f1x_per)", + "executable": "./target/thumbv7m-none-eabi/debug/examples/sleep_stop", "configFiles": [ "interface/stlink.cfg", - "target/stm32f4x.cfg" + "stm32f1x_per.cfg" ], "swoConfig": { "enabled": true, @@ -203,33 +50,19 @@ "label": "Name", "port": 0 } - ] + ], }, "cwd": "${workspaceRoot}" }, { "type": "cortex-debug", "request": "launch", - "servertype": "openocd", - "name": "panic", - "executable": "./target/thumbv7em-none-eabihf/debug/examples/panic", - "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 - } - ] - }, + "servertype": "bmp", + "name": "sleep_stop (bmp)", + "executable": "./target/thumbv7m-none-eabi/debug/examples/sleep_stop", + "device": "STM32F103RB", + "BMPGDBSerialPort": "/dev/ttyACM1", + "targetId": 1, "cwd": "${workspaceRoot}" }, ] diff --git a/Cargo.toml b/Cargo.toml index 8f77950..ee3f134 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,10 +11,10 @@ # will likely look very different (and much more reasonable) [package] -name = "cortex-m-quickstart" +name = "low-power-stm32f103" version = "0.3.1" authors = ["Per Lindgren <per.lindgren@ltu.se>"] -description = "Low Power Experiments on the Nucleo 64 stm32f401re" +description = "Low Power Experiments on the Nucleo 64 stm32f103" keywords = ["arm", "cortex-m", "template"] categories = ["embedded", "no-std"] license = "MIT OR Apache-2.0" @@ -38,9 +38,8 @@ version = "0.2.0" [dependencies.panic-semihosting] version = "0.3.0" -[dependencies.stm32f40x] -path = "../STM32F40x" +[dependencies.stm32f103xx] features = ["rt"] -version = "0.3.0" +version = "0.10.0" #panic = "abort" \ No newline at end of file diff --git a/examples/sleep_stop.rs b/examples/sleep_stop.rs index 3e5c5cb..fbeb256 100644 --- a/examples/sleep_stop.rs +++ b/examples/sleep_stop.rs @@ -6,8 +6,8 @@ extern crate cortex_m; #[macro_use(interrupt)] -extern crate stm32f40x; -use stm32f40x::Interrupt; +extern crate stm32f103xx; +use stm32f103xx::Interrupt; #[macro_use(entry, exception)] extern crate cortex_m_rt as rt; @@ -18,43 +18,16 @@ use rt::ExceptionFrame; use cortex_m::peripheral::Peripherals; -fn analog_input() { - #[allow(non_snake_case)] - let GPIOC = unsafe { &*stm32f40x::GPIOC::ptr() }; - #[allow(non_snake_case)] - let GPIOD = unsafe { &*stm32f40x::GPIOD::ptr() }; - #[allow(non_snake_case)] - let GPIOE = unsafe { &*stm32f40x::GPIOE::ptr() }; - // #[allow(non_snake_case)] - // let GPIOF = unsafe { &*stm32f40x::GPIOF::ptr() }; - // #[allow(non_snake_case)] - // let GPIOG = unsafe { &*stm32f40x::GPIOG::ptr() }; - // #[allow(non_snake_case)] - // let GPIOH = unsafe { &*stm32f40x::GPIOH::ptr() }; - // #[allow(non_snake_case)] - // let GPIOI = unsafe { &*stm32f40x::GPIOI::ptr() }; - let r1 = GPIOC.moder.read().bits(); - GPIOC.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // analog mode - GPIOD.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // analog mode - GPIOE.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // analog mode - // GPIOF.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // analog mode - // GPIOG.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // analog mode - // GPIOH.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // analog mode - // GPIOI.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // analog mode - - let r2 = GPIOC.moder.read().bits(); - // asm::bkpt(); -} - // 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| { + let dbg = unsafe { &*stm32f103xx::DBG::ptr() }; + let afio = unsafe { &*stm32f103xx::AFIO::ptr() }; + // #[allow(non_snake_case)] + // let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() }; + // #[allow(non_snake_case)] + // let GPIOB = unsafe { &*stm32f40x::GPIOB::ptr() }; + dbg.cr.modify(|_, w| { w.dbg_sleep() .set_bit() .dbg_stop() @@ -64,11 +37,14 @@ fn dbg_enable() { .trace_ioen() .set_bit() }); - GPIOA.moder.reset(); - GPIOA.pupdr.reset(); - GPIOB.moder.reset(); - GPIOB.pupdr.reset(); + // 31.4.2, table 220 + // afio.mapr.modify(|_, w| unsafe { w.swj_cfg().bits(0b000) }); // all debugging + // GPIOA.moder.reset(); + // GPIOA.pupdr.reset(); + + // GPIOB.moder.reset(); + // GPIOB.pupdr.reset(); } // set the MCU in true sleepdeep mode on WFI/WFE @@ -76,172 +52,399 @@ fn dbg_enable() { fn dbg_disable() { #[allow(non_snake_case)] - let DBG = unsafe { &*stm32f40x::DBG::ptr() }; + let DBG = unsafe { &*stm32f103xx::DBG::ptr() }; + let afio = unsafe { &*stm32f103xx::AFIO::ptr() }; #[allow(non_snake_case)] - let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() }; + let GPIOA = unsafe { &*stm32f103xx::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() - }); + let GPIOB = unsafe { &*stm32f103xx::GPIOB::ptr() }; + #[allow(non_snake_case)] + let GPIOC = unsafe { &*stm32f103xx::GPIOC::ptr() }; // set all gpio to analog input - // let _a_moder_ = GPIOA.moder.read().bits(); - // let _b_moder_ = GPIOB.moder.read().bits(); + let _a_crl_ = GPIOA.crl.read().bits(); + let _a_crh_ = GPIOA.crh.read().bits(); + // let _b_moder_ = GPIOB.crl.read().bits(); // let _a_pupdr_ = GPIOA.pupdr.read().bits(); // let _b_pupdr_ = GPIOB.pupdr.read().bits(); // 0.142 mA without manipulating GPIO/GPIOB + let v = GPIOA.crl.read().bits(); + + // GPIOA.crl.write(|w| unsafe { w.bits(0x0) }); // PA l, analog + // GPIOA.crl.modify(|_, w| w.cnf1().bits(0b10)); // PA1 input pull up/down + + // set PA0, PA2-7, to analog mode + GPIOA.crl.modify(|_, w| { + w.cnf0() + .bits(0b00) + .cnf2() + .bits(0b00) + .cnf3() + .bits(0b00) + .cnf4() + .bits(0b00) + .cnf5() + .bits(0b00) + .cnf6() + .bits(0b00) + .cnf7() + .bits(0b00) + }); - GPIOA.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // PA, analog - GPIOA.moder.modify(|_, w| w.moder1().input_mode()); // PA1, input_mode - GPIOB.pupdr.write(|w| unsafe { w.bits(0) }); // PA, floating - GPIOA.pupdr.modify(|_, w| w.pupdr1().pull_up()); // PA1, pull up + // set PA8-15, to analog mode + GPIOA.crh.modify(|_, w| { + w.cnf8() + .bits(0b00) + .cnf9() + .bits(0b00) + .cnf10() + .bits(0b00) + .cnf11() + .bits(0b00) + .cnf12() + .bits(0b00) + .cnf13() + .bits(0b00) + .cnf14() + .bits(0b00) + .cnf15() + .bits(0b00) + }); - GPIOB.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // PB, analog - GPIOB.pupdr.write(|w| unsafe { w.bits(0) }); // PB, floating + GPIOB.crl.modify(|_, w| { + w.cnf0() + .bits(0b00) + .cnf1() + .bits(0b00) + .cnf2() + .bits(0b00) + .cnf3() + .bits(0b00) + .cnf4() + .bits(0b00) + .cnf5() + .bits(0b00) + .cnf6() + .bits(0b00) + .cnf7() + .bits(0b00) + }); + + // set PA8-15, to analog mode + GPIOB.crh.modify(|_, w| { + w.cnf8() + .bits(0b00) + .cnf9() + .bits(0b00) + .cnf10() + .bits(0b00) + .cnf11() + .bits(0b00) + .cnf12() + .bits(0b00) + .cnf13() + .bits(0b00) + .cnf14() + .bits(0b00) + .cnf15() + .bits(0b00) + }); + + GPIOC.crl.modify(|_, w| { + w.cnf0() + .bits(0b00) + .cnf1() + .bits(0b00) + .cnf2() + .bits(0b00) + .cnf3() + .bits(0b00) + .cnf4() + .bits(0b00) + .cnf5() + .bits(0b00) + .cnf6() + .bits(0b00) + .cnf7() + .bits(0b00) + }); + + // set PA8-15, to analog mode + GPIOC.crh.modify(|_, w| { + w.cnf8() + .bits(0b00) + .cnf9() + .bits(0b00) + .cnf10() + .bits(0b00) + .cnf11() + .bits(0b00) + .cnf12() + .bits(0b00) + .cnf13() + .bits(0b00) + .cnf14() + .bits(0b00) + .cnf15() + .bits(0b00) + }); + + let vl = GPIOA.crl.read().bits(); + let vh = GPIOA.crh.read().bits(); + // GPIOA.crh.write(|w| unsafe { w.bits(0x0) }); // PA h, analog + // GPIOA.moder.modify(|_, w| w.moder1().input_mode()); // PA1, input_mode + // GPIOB.pupdr.write(|w| unsafe { w.bits(0) }); // PA, floating + // GPIOA.pupdr.modify(|_, w| w.pupdr1().pull_up()); // PA1, pull up + + let _a_crl = GPIOA.crl.read().bits(); + let _a_crh = GPIOA.crh.read().bits(); - // 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(); + + // let swj = afio.mapr.read().bits(); + + // DBG.cr.modify(|_, w| { + // w.dbg_sleep() + // .clear_bit() + // .dbg_stop() + // .clear_bit() + // .dbg_standby() + // .clear_bit() + // .trace_ioen() + // .clear_bit() + // }); + + // 31.4.2, table 220 + // afio.mapr.modify(|_, w| unsafe { w.swj_cfg().bits(0b100) }); // no debugging + + // GPIOB.moder.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // PB, analog + // GPIOB.pupdr.write(|w| unsafe { w.bits(0) }); // PB, floating } // the program entry point is ... entry!(main); -// ... this never ending function + +fn clock_out(rcc: &stm32f103xx::RCC, gpioa: &stm32f103xx::GPIOA) { + // output MCO to pin PA8 + // mco : SYSCLK = 0b100, 8.2.10 + rcc.cfgr.modify(|_, w| unsafe { w.mco().bits(0b100) }); + + // power on GPIOa, + // clock enable gpioa for clock output + rcc.apb2enr.modify(|_, w| w.iopaen().set_bit()); + + // 9.2.2 + // PA8 50 MHz, push pull alternate function + gpioa + .crh + .modify(|_, w| w.mode8().output50().cnf8().alt_push()); +} + +// bind the EXTI1 handler +interrupt!(EXTI1, exti1); + +// the exti1 interrupt implementation +fn exti1() { + // dbg_enable(); + led(10); + asm::bkpt(); + // led(10); + // clear pending state + let exti = unsafe { &*stm32f103xx::EXTI::ptr() }; + exti.pr.write(|w| w.pr1().set_bit()); + // dbg_disable(); +} + +fn led(i: u8) { + #[allow(non_snake_case)] + let GPIOC = unsafe { &*stm32f103xx::GPIOC::ptr() }; + GPIOC.crh.modify(|_, w| w.mode13().output()); // PC13 set as output + for _ in 0..i { + for _ in 0..1000 {} + GPIOC.bsrr.write(|w| w.br13().set_bit()); + for _ in 0..1000 {} + GPIOC.bsrr.write(|w| w.bs13().set_bit()); + } + GPIOC.crh.modify(|_, w| w.mode13().input()); // PC13 set as input +} + fn main() -> ! { - let r = stm32f40x::Peripherals::take().unwrap(); + let r = stm32f103xx::Peripherals::take().unwrap(); let mut p = Peripherals::take().unwrap(); // enable the EXTI1 interrupt p.NVIC.enable(Interrupt::EXTI1); - // enable gpioa, gpiob - r.RCC.ahb1enr.modify(|_, w| { - w.gpioaen() - .set_bit() - .gpioben() - .set_bit() - .gpiocen() - .set_bit() - .gpioden() - .set_bit() - .gpioeen() - .set_bit() - .gpiofen() - .set_bit() - }); - // asm::bkpt(); - analog_input(); - // asm::bkpt(); - let mut read: u32 = 0; + // clock_out(&r.RCC, &r.GPIOA); + asm::bkpt(); - // PA1 pull up - r.GPIOA.pupdr.modify(|r, w| w.pupdr1().pull_up()); - #[allow(non_snake_case)] - let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() }; + // PC13, led + // r.RCC.apb2enr.modify(|_, w| w.iopcen().set_bit()); // clock enable gpioc + // r.GPIOC.crh.modify(|_, w| w.mode13().output()); // PC13 set as output + // led(10); asm::nop(); - // SYSCFG.exti1 is PAx (0000) by reset, so we don't change it + // clock enable gpioa, gpiob, gpioc + r.RCC.apb2enr.modify(|_, w| { + w.iopaen().set_bit().iopben().set_bit().iopcen().set_bit() + }); + + // enable alternate function + r.RCC.apb2enr.modify(|_, w| w.afioen().set_bit()); + r.AFIO.exticr1.modify(|_, w| unsafe { w.exti1().bits(0) }); + + // input by default + // r.GPIOA.crl.modify(|_, w| w.cnf1().bits(0b10)); // PA1 input pull up/down + // r.GPIOA.odr.modify(|_, w| w.odr1().set_bit()); // PA1 input pull up + + r.EXTI.ftsr.modify(|_, w| w.tr1().set_bit()); // EXTI1 trigger on falling, enable tr1 + r.EXTI.imr.modify(|_, w| w.mr1().set_bit()); // EXTI1 interrupt mask register, enable mr1 + // r.EXTI.emr.modify(|_, w| w.mr1().set_bit()); // EXTI1 event on mask register, enabel mr1 - // 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()); - // clear triggering event - r.EXTI.pr.modify(|_, w| w.pr1().set_bit()); + // test raising a software interrupt + // r.EXTI.swier.write(|w| w.swier1().set_bit()); // trigger sw interrupt + + let pr = r.EXTI.pr.read().bits(); + + // r.EXTI.pr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); // clear all pending interrups/events, a bit ugly p.SCB.set_sleepdeep(); - // enable pwr + + // clock enbable pwren r.RCC.apb1enr.modify(|_, w| w.pwren().set_bit()); - // set standby mode - // r.PWR - // .cr - // .write(|w| unsafe { w.bits((1 << 10) | 0x0000_8000) }); + + // stop mode configuration pdds clear and regulator in low power mode r.PWR .cr - .modify(|_, w| w.pdds().clear_bit().lpds().set_bit().fpds().set_bit()); + .modify(|_, w| w.pdds().clear_bit().lpds().set_bit()); - // r.PWR - // .cr - // .modify(|_, w| w.pdds().clear_bit().lpds().clear_bit()); - // blink(); + // regulator in run mode (on) + // r.PWR.cr.modify(|_, w| w.pdds().clear_bit()); - // p.NVIC.set_pending(Interrupt::EXTI1); + let pwr = r.PWR.cr.read().bits(); + asm::nop(); - asm::bkpt(); + dbg_disable(); + r.EXTI.pr.write(|w| w.pr1().set_bit()); 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(); - } + //led(10); } - 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()); -} +// .gpiocen() +// .set_bit() +// .gpioden() +// .set_bit() +// .gpioeen() +// .set_bit() +// .gpiofen() +// .set_bit() +// }); +// // asm::bkpt(); +// analog_input(); +// // asm::bkpt(); + +// let mut read: u32 = 0; + +// // PA1 pull up +// r.GPIOA.pupdr.modify(|r, w| w.pupdr1().pull_up()); +// #[allow(non_snake_case)] +// let GPIOA = unsafe { &*stm32f40x::GPIOA::ptr() }; + +// asm::nop(); + +// // SYSCFG.exti1 is PAx (0000) by reset, so we don't change it + +// // 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()); +// // clear triggering event +// r.EXTI.pr.modify(|_, w| w.pr1().set_bit()); + +// 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); + +// asm::bkpt(); +// 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); diff --git a/memory.x b/memory.x index f4df782..86aa62e 100644 --- a/memory.x +++ b/memory.x @@ -1,8 +1,8 @@ MEMORY { /* NOTE K = KiBi = 1024 bytes */ - FLASH : ORIGIN = 0x08000000, LENGTH = 256K - RAM : ORIGIN = 0x20000000, LENGTH = 40K + FLASH : ORIGIN = 0x08000000, LENGTH = 64K + RAM : ORIGIN = 0x20000000, LENGTH = 20K } /* This is where the call stack will be allocated. */ diff --git a/stm32f1x_per.cfg b/stm32f1x_per.cfg new file mode 100644 index 0000000..e0e7643 --- /dev/null +++ b/stm32f1x_per.cfg @@ -0,0 +1,80 @@ +# script for stm32f1x family + +# +# stm32 devices support both JTAG and SWD transports. +# +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32f1x +} + +set _ENDIAN little + +# Work-area is a space in RAM used for flash programming +# By default use 4kB (as found on some STM32F100s) +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x1000 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + # See STM Document RM0008 Section 26.6.3 + set _CPUTAPID 0x3ba00477 + } { + # this is the SW-DP tap id not the jtag tap id + set _CPUTAPID 0x1ba01477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +if {[using_jtag]} { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# flash size will be probed +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME + +# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz +adapter_khz 1000 + +adapter_nsrst_delay 100 +if {[using_jtag]} { + jtag_ntrst_delay 100 +} + +reset_config srst_nogate + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +$_TARGETNAME configure -event examine-end { + # DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP | + # DBG_STANDBY | DBG_STOP | DBG_SLEEP + # mmw 0xE0042004 0x00000307 0 +} + +$_TARGETNAME configure -event trace-config { + # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync + # change this value accordingly to configure trace pins + # assignment + mmw 0xE0042004 0x00000020 0 +} -- GitLab