Skip to content
Snippets Groups Projects
Commit 0e4ce287 authored by Per Lindgren's avatar Per Lindgren
Browse files

optional bare6 + example of software reset

parent c03d4f7d
Branches
No related tags found
No related merge requests found
...@@ -88,6 +88,56 @@ ...@@ -88,6 +88,56 @@
"cwd": "${workspaceRoot}" "cwd": "${workspaceRoot}"
}, },
// Launch configuration for `examples` // Launch configuration for `examples`
// - debug
// - semihosting
// - ITM/SWO tracing to file/fifo `/tmp/itm.fifo`
// - run to main
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"name": "itm fifo (debug) stm32f4",
"preLaunchTask": "cargo build --example --features stm32f4",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
"configFiles": [
"interface/stlink.cfg",
// "interface/stlink-v2-1.cfg", // deprecated setup script
"target/stm32f4x.cfg"
],
"postLaunchCommands": [
"monitor arm semihosting enable",
"monitor tpiu config internal /tmp/itm.fifo uart off 16000000",
"monitor itm port 0 on"
],
"runToMain": true,
"cwd": "${workspaceRoot}"
},
// Launch configuration for `examples`
// - debug
// - semihosting
// - ITM/SWO tracing to file/fifo `/tmp/itm.fifo`
// - run to main
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"name": "itm fifo (debug) rtfm",
"preLaunchTask": "cargo build --example --features rtfm",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
"configFiles": [
"interface/stlink.cfg",
// "interface/stlink-v2-1.cfg", // deprecated setup script
"target/stm32f4x.cfg"
],
"postLaunchCommands": [
"monitor arm semihosting enable",
"monitor tpiu config internal /tmp/itm.fifo uart off 16000000",
"monitor itm port 0 on"
],
"runToMain": true,
"cwd": "${workspaceRoot}"
},
// Launch configuration for `examples`
// - release // - release
// - semihosting // - semihosting
// - ITM/SWO tracing to file/fifo `/tmp/itm.fifo` // - ITM/SWO tracing to file/fifo `/tmp/itm.fifo`
...@@ -121,8 +171,8 @@ ...@@ -121,8 +171,8 @@
"type": "cortex-debug", "type": "cortex-debug",
"request": "launch", "request": "launch",
"servertype": "openocd", "servertype": "openocd",
"name": "itm fifo 64MHz (release)", "name": "itm fifo 64MHz (release) stm32f4",
"preLaunchTask": "cargo build --example --release", "preLaunchTask": "cargo build --example --release --features stm32f4",
"executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}", "executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
"configFiles": [ "configFiles": [
"interface/stlink.cfg", "interface/stlink.cfg",
......
...@@ -41,8 +41,32 @@ ...@@ -41,8 +41,32 @@
}, },
{ {
"type": "shell", "type": "shell",
"label": "cargo build --example --release", "label": "cargo build --example --features stm32f4",
"command": "cargo build --example ${fileBasenameNoExtension} --release", "command": "cargo build --example ${fileBasenameNoExtension} --features stm32f4",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$rustc"
]
},
{
"type": "shell",
"label": "cargo build --example --features rtfm",
"command": "cargo build --example ${fileBasenameNoExtension} --features rtfm",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$rustc"
]
},
{
"type": "shell",
"label": "cargo build --example --release --features stm32f4",
"command": "cargo build --example ${fileBasenameNoExtension} --release --features stm32f4",
"group": { "group": {
"kind": "build", "kind": "build",
"isDefault": true "isDefault": true
......
...@@ -53,6 +53,10 @@ bench = false ...@@ -53,6 +53,10 @@ bench = false
name = "device" name = "device"
required-features = ["stm32f4"] required-features = ["stm32f4"]
[[example]]
name = "bare6"
required-features = ["stm32f4"]
[[example]] [[example]]
name = "serial" name = "serial"
required-features = ["stm32f4xx-hal"] required-features = ["stm32f4xx-hal"]
...@@ -85,9 +89,14 @@ required-features = ["rtfm"] ...@@ -85,9 +89,14 @@ required-features = ["rtfm"]
name = "rtfm_blinky_msg3" name = "rtfm_blinky_msg3"
required-features = ["rtfm"] required-features = ["rtfm"]
[[example]]
name = "rtfm_blinky_sw_reset"
required-features = ["rtfm"]
# for more info see, https://doc.rust-lang.org/rustc/codegen-options/index.html
[profile.dev] [profile.dev]
opt-level = 1 # opt-level = 1 # better optimization (may optimize out symbols)
codegen-units = 16 # codegen-units = 16
debug = true debug = true
lto = false lto = false
......
...@@ -189,17 +189,19 @@ fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) { ...@@ -189,17 +189,19 @@ fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) {
loop { loop {
// set PA5 high // set PA5 high
gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led) gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led)
// alternatively to set the bit high we can
// read the value, or with PA5 (bit 5) and write back // alternatively to set the bit high we can
// gpioa.ODR.write(gpioa.ODR.read() | (1 << 5)); // read the value, or with PA5 (bit 5) and write back
// gpioa.ODR.write(gpioa.ODR.read() | (1 << 5));
wait(10_000); wait(10_000);
// set PA5 low // set PA5 low
gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led) gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led)
// alternatively to clear the bit we can
// read the value, mask out PA5 (bit 5) and write back // alternatively to clear the bit we can
// gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5)); // read the value, mask out PA5 (bit 5) and write back
// gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5));
wait(10_000); wait(10_000);
} }
} }
......
//! bare6.rs
//!
//! Clocking
//!
//! What it covers:
//! - using svd2rust generated API
//! - setting the clock via script (again)
//! - routing the clock to a PIN for monitoring by an oscilloscope
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m::{iprintln, peripheral::itm::Stim};
use cortex_m_rt::entry;
use stm32f4::stm32f401::{self, DWT, GPIOA, GPIOC, RCC};
#[entry]
fn main() -> ! {
let p = stm32f401::Peripherals::take().unwrap();
let mut c = stm32f401::CorePeripherals::take().unwrap();
let stim = &mut c.ITM.stim[0];
iprintln!(stim, "bare6");
c.DWT.enable_cycle_counter();
unsafe {
c.DWT.cyccnt.write(0);
}
let t = DWT::get_cycle_count();
iprintln!(stim, "{}", t);
clock_out(&p.RCC, &p.GPIOC);
idle(stim, p.RCC, p.GPIOA);
}
// user application
fn idle(stim: &mut Stim, rcc: RCC, gpioa: GPIOA) -> ! {
iprintln!(stim, "idle");
// power on GPIOA, RM0368 6.3.11
rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
// configure PA5 as output, RM0368 8.4.1
gpioa.moder.modify(|_, w| w.moder5().bits(1));
// at 16 Mhz, 8_000_000 cycles = period 0.5s
// at 64 Mhz, 4*8_000_000 cycles = period 0.5s
// let cycles = 8_000_000;
let cycles = 4 * 8_000_000;
loop {
iprintln!(stim, "on {}", DWT::get_cycle_count());
// set PA5 high, RM0368 8.4.7
gpioa.bsrr.write(|w| w.bs5().set_bit());
wait_cycles(cycles);
iprintln!(stim, "off {}", DWT::get_cycle_count());
// set PA5 low, RM0368 8.4.7
gpioa.bsrr.write(|w| w.br5().set_bit());
wait_cycles(cycles);
}
}
// uses the DWT.CYCNT
// doc: ARM trm_100166_0001_00_en.pdf, chapter 9.2
// we use the `cortex-m` abstraction, as re-exported by the stm32f40x
fn wait_cycles(nr_cycles: u32) {
let t = DWT::get_cycle_count().wrapping_add(nr_cycles);
while (DWT::get_cycle_count().wrapping_sub(t) as i32) < 0 {}
}
// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
// rcc, chapter 6
// gpio, chapter 8
fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
// output MCO2 to pin PC9
// mco2 : SYSCLK = 0b00
// mcopre : divide by 4 = 0b110
rcc.cfgr
.modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) });
// power on GPIOC, RM0368 6.3.11
rcc.ahb1enr.modify(|_, w| w.gpiocen().set_bit());
// MCO_2 alternate function AF0, STM32F401xD STM32F401xE data sheet
// table 9
// AF0, gpioc reset value = AF0
// configure PC9 as alternate function 0b10, RM0368 6.2.10
gpioc.moder.modify(|_, w| w.moder9().bits(0b10));
// otyper reset state push/pull, in reset state (don't need to change)
// ospeedr 0b11 = very high speed
gpioc.ospeedr.modify(|_, w| w.ospeedr9().bits(0b11));
}
// Optional assignment
// 0. Compile and run the example, in 16Mhz
//
// > cargo build --example bare6 --features "stm32f4"
// (or use the vscode build task)
//
// The "stm32f4" feature enables the optional dependency "stm32f4", with the "stm32f401" feature set
//
// Cargo.toml:
//
// [dependencies.stm32f4]
// version = "0.9.0"
// features = ["stm32f401", "rt"]
// optional = true
// (this will provide the "stm32f401" interrupt vector through the "rt" feature)
//
// [[example]]
// name = "bare6"
// required-features = ["stm32f4"]
// (this will require/force you to use the stm32f4 feature)
//
// 1. The processor SYSCLK defaults to HCI 16Mhz
// (this is what you get after a `monitor reset halt`).
//
// Confirm that your ITM dump traces the init, idle and led on/off.
// Make sure your TPIU is set to a system clock at 16Mhz
//
// What is the frequency of blinking?
//
// ** your answer here **
//
// commit your answers (bare6_1)
//
// 2. Now connect an oscilloscope to PC9, which is set to
// output the MCO2.
//
// What is the frequency of MCO2 read by the oscilloscope?
//
// ** your answer here **
//
// Compute the value of SYSCLK based on the oscilloscope reading
//
// ** your answer here **
//
// What is the peak to peak reading of the signal?
//
// ** your answer here **
//
// Make a folder called "pictures" in your git project.
// Make a screen dump or photo of the oscilloscope output.
// Save the the picture as "bare_6_16mhz_high_speed".
//
// Commit your answers (bare6_2)
//
// 3. Now run the example in 64Mz
// You can do that by issuing a `monitor reset init`
// which reprograms SYSCLK to 4*HCI.
//
//
// Confirm that your ITM dump traces the init, idle and led on/off
// (make sure your TPIU is set to a system clock at 64Mhz)
//
// Uncommnet: `let cycles = 4 * 8_000_000;
//`
// What is the frequency of blinking?
//
// ** your answer here **
//
// Commit your answers (bare6_3)
//
// 4. Repeat experiment 2
//
// What is the frequency of MCO2 read by the oscilloscope?
//
// ** your answer here **
//
// Compute the value of SYSCLK based on the oscilloscope reading.
//
// ** your answer here **
//
// What is the peak to peak reading of the signal?
//
// ** your answer here **
//
// Make a screen dump or photo of the oscilloscope output.
// Save the the picture as "bare_6_64mhz_high_speed".
//
// Commit your answers (bare6_4)
//
// 5. In the `clock_out` function, the setup of registers is done through
// setting bit-pattens manually, e.g.
// rcc.cfgr
// .modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) });
//
// However based on the vendor SVD file the svd2rust API provides
// a better abstraction, based on pattern enums and functions.
//
// To view the API you can generate documentation for your crate:
//
// > cargo doc --features "stm32f4" --open
//
// By searching for `mco2` you find the enumerations and functions.
// So here
// `w.mco2().bits{0b00}` is equivalent to
// `w.mco2().sysclk()` and improves readability.
//
// Replace all bit-patterns used by the function name equivalents.
//
// Test that the application still runs as before.
//
// Commit your code (bare6_4)
\ No newline at end of file
#![deny(unsafe_code)]
// #![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m;
use cortex_m::peripheral::DWT;
use panic_halt as _;
use rtfm::cyccnt::U32Ext;
use stm32f4xx_hal::stm32;
#[rtfm::app(device = stm32f4xx_hal::stm32, monotonic = rtfm::cyccnt::CYCCNT, peripherals = true)]
const APP: () = {
#[init(schedule = [toggle])]
fn init(cx: init::Context) {
let mut core = cx.core;
let device = cx.device;
// Initialize (enable) the monotonic timer (CYCCNT)
core.DCB.enable_trace();
// required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7)
DWT::unlock();
core.DWT.enable_cycle_counter();
// semantically, the monotonic timer is frozen at time "zero" during `init`
// NOTE do *not* call `Instant::now` in this context; it will return a nonsense value
let now = cx.start; // the start time of the system
// power on GPIOA, RM0368 6.3.11
device.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
// configure PA5 as output, RM0368 8.4.1
device.GPIOA.moder.modify(|_, w| w.moder5().bits(1));
cx.schedule
.toggle(now + 8_000_000.cycles(), true, device.GPIOA, core.SCB, 1)
.ok();
}
#[task(schedule= [toggle])]
fn toggle(
cx: toggle::Context,
toggle: bool,
gpioa: stm32::GPIOA,
mut scb: stm32::SCB,
mut state: u8,
) {
if toggle {
gpioa.bsrr.write(|w| w.bs5().set_bit());
} else {
gpioa.bsrr.write(|w| w.br5().set_bit());
}
state += 1;
if state == 10 {
//state = 0;
// scb.system_reset();
cortex_m::peripheral::SCB::sys_reset();
};
cx.schedule
.toggle(
cx.scheduled + (state as u32 * 400_000).cycles(),
!toggle,
gpioa,
scb,
state,
)
.ok();
}
extern "C" {
fn EXTI0();
}
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment