diff --git a/.vscode/launch.json b/.vscode/launch.json index b61b652ebe740398cfaf97c44b2e864c70208fa9..df1f5da4233c32f202ce0528ab3bf8d004983751 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -226,6 +226,64 @@ ], "cwd": "${workspaceRoot}" }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "bare2 (debug)", + "preLaunchTask": "cargo build --example bare2", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare2", + "postLaunchCommands": [ + "monitor arm semihosting enable" + ], + "swoConfig": { + "enabled": true, + "cpuFrequency": 16000000, + "swoFrequency": 2000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "ITM", + "port": 0 + } + ] + }, + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f4x.cfg" + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "bare2 (release)", + "preLaunchTask": "cargo build --example bare2", + "executable": "./target/thumbv7em-none-eabihf/release/examples/bare2", + "postLaunchCommands": [ + "monitor arm semihosting enable" + ], + "swoConfig": { + "enabled": true, + "cpuFrequency": 16000000, + "swoFrequency": 2000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "ITM", + "port": 0 + } + ] + }, + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f4x.cfg" + ], + "cwd": "${workspaceRoot}" + }, { "type": "cortex-debug", "request": "launch", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d0ca15ac546b33228ab89ae5092ecab195ade166..6bd84bc5bb4d224239ac82f575acfb899227221e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -111,5 +111,29 @@ "isDefault": true } }, + { + "type": "shell", + "label": "cargo build --example bare2", + "command": "cargo build --example bare2", + "problemMatcher": [ + "$rustc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "cargo build --example bare2 --release", + "command": "cargo build --example bare2 --release", + "problemMatcher": [ + "$rustc" + ], + "group": { + "kind": "build", + "isDefault": true + } + } ] } \ No newline at end of file diff --git a/examples/bare1.rs b/examples/bare1.rs new file mode 100644 index 0000000000000000000000000000000000000000..4a10eced59853290b20228d905f2793f1ee0bbcd --- /dev/null +++ b/examples/bare1.rs @@ -0,0 +1,161 @@ +//! bare1.rs +//! +//! Tracing and assembly code +//! +//! What it covers +//! - tracing over semihosting and ITM +//! - assembly calls and inline assembly +//! - more on arithmetics +//! --- + +#![no_main] +#![no_std] + +extern crate panic_halt; + +use cortex_m::{iprintln, Peripherals}; +use cortex_m_rt::entry; +use cortex_m_semihosting::hprintln; + +#[entry] +fn main() -> ! { + let mut p = Peripherals::take().unwrap(); + let stim = &mut p.ITM.stim[0]; + + let mut x = 27; + iprintln!(stim, "x = {:?}", x); + hprintln!("x = {:?}", x).unwrap(); + loop { + x += 1; + cortex_m::asm::nop(); + cortex_m::asm::bkpt(); + x -= 1; + } +} + +// 0. Setup +// For this example we will use the `nightly` compiler +// to get true inline assembly. +// +// > rustup override set nightly +// +// You may need/want to install addititonal components also), +// to that end look at the install section in the README.md. +// If you change toolchain, exit and re-start `vscode`. +// +// 1. Build and run the application +// Look at the `hello.rs` and `itm.rs` examples to setup the tracing. +// +// When debugging the application it should get stuck in the +// loop, (press pause/suspend to verify this). +// what is the output in the ITM console +// +// ** your answer here ** +// +// What is the output in the semihosting (openocd) console +// ** your answer here ** +// +// commit your answers (bare1_1) +// +// 2. Inspecting the generated assembly code +// If in `vcsode` the gdb console in DEBUG CONSOLE +// What is the output of: +// (gdb) disassemble +// +// ** your answer here ** +// +// commit your answers (bare1_2) +// +// 3. Now remove the comment for `cortex_m::asm::nop()`. +// Rebuild and debug, pause the program. +// What is the output of: +// (gdb) disassemble +// +// ** your answer here ** +// +// commit your answers (bare1_3) +// +// 4. Now remove the comment for `cortex_m::asm::bkpt()` +// Rebuild and debug, let the program run until it halts. +// What is the output of: +// (gdb) disassemble +// +// ** your answer here ** +// +// commit your answers (bare1_4) +// +// 5. Release mode (optimized builds). +// Rebuild `bare1.rs` in release (optimized mode). +// Compare the generated assembly for the loop +// between the dev (unoptimized) and release (optimized) build. +// +// ** your answer here ** +// +// commit your answers (bare1_5) +// +// Tips: The optimized build should have some 8 instructions +// while the debug (dev) build should have > 20 instructions +// (both counting the inner loop only). The debug build +// should have additional code that call panic if the additon +// wraps (and in such case call panic). +// +// Discussion: +// In release (optimized) mode the addition is unchecked, +// so there is a semantic difference here in between +// the dev and release modes. This is motivited by: +// 1) efficiency, unchecked is faster +// 2) convenience, it would be inconvenient to explicitly use +// wrapping arithmetics, and wrapping is what the programmer +// typically would expect in any case. So the check +// in dev/debug mode is just there for some extra safety +// if your intention is NON-wrapping arithmetics. +// +// 6. *Optional +// You can pass additional flags to the Rust `rustc` compiler. +// +// `-Z force-overflow-checks=off` +// +// Under this flag, code is never generated for oveflow checking. +// You can enable this flag (uncomment the corresponding flag in +// the `.cargo/config` file.) +// +// What is now the disassembly of the loop: +// +// ** your answer here ** +// +// commit your answers (bare1_6) +// +// Now restore the `.cargo/config` to its original state. +// +// 7. *Optional +// There is another way to conveniently use wrapping arithmetics +// without passing flags to the compiler. +// +// https://doc.rust-lang.org/std/num/struct.Wrapping.html +// +// Rewrite the code using this approach. +// +// What is now the disassembly of the code in dev mode? +// +// ** your answer here ** +// +// What is now the disassembly of the code in release mode? +// +// ** your answer here ** +// +// commit your answers (bare1_7) +// +// Final discussion: +// +// Embedded code typically is performance sensitve, hence +// it is important to understand how code is generated +// to achieve efficient implementations. +// +// Moreover, arithmetics are key to processing of data, +// so its important that we are in control over the +// computations. E.g. comupting checksums, hashes, cryptos etc. +// all require precise control over wrapping vs. overflow behaviour. +// +// If you write a library depending on wrapping arithmetics +// do NOT rely on a compiler flag. (The end user might compile +// it without this flag enabled, and thus get erronous results.)