diff --git a/.vscode/launch.json b/.vscode/launch.json index 4ffb6ad5b6c032da255359b358bad4bdc133afa2..9885634c6f7d28f1b19065368d43da87d3465813 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -155,6 +155,19 @@ "svdFile": "STM32F413.svd", "cwd": "${workspaceRoot}" }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "bare0 (debug)", + "preLaunchTask": "cargo build --example bare0", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare0", + "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 b535eecf7e8abb1c6e23621e8a0f2dcdedc2553a..d671b64862e64c639d36431ad9c7aeba30046529 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -75,5 +75,17 @@ "isDefault": true } }, + { + "type": "shell", + "label": "cargo build --example bare0", + "command": "cargo build --example bare0", + "problemMatcher": [ + "$rustc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, ] } \ No newline at end of file diff --git a/examples/bare0.rs b/examples/bare0.rs new file mode 100644 index 0000000000000000000000000000000000000000..db9ae60dedf91c7af47ec02208e23d90577d8cc3 --- /dev/null +++ b/examples/bare0.rs @@ -0,0 +1,101 @@ +//! bare0.rs +//! +//! Simple bare metal application +//! What it covers: +//! - constants +//! - global (static) variables +//! - checked vs. wrapping arithmetics +//! - safe and unsafe code +//! - making a safe API +//! +// build without the Rust standard library +#![no_std] +// no standard main, we declare main using [entry] +#![no_main] + +extern crate panic_halt; + +// Minimal runtime / startup for Cortex-M microcontrollers +use cortex_m_rt::entry; + +// a constant (cannot be changed) +const X_INIT: u32 = 10; + +// global mutabale variables (changed using unsafe code) +static mut X: u32 = X_INIT; +static mut Y: u32 = 0; + +#[entry] +fn main() -> ! { + // local mutabale variable (changed in safe code) + let mut x = unsafe { X }; + + loop { + x += 1; // <- place breakpoint here (3) + unsafe { + X += 1; + Y = X; + assert!(x == X && X == Y); + } + } +} + +// 1. run the program in the debugger, +// let the program run for a while and then press pause +// look in the (Local -vscode) Variables view what do you find +// ** your answer here ** +// +// in the Expressions (WATCH -vscode) view add X and Y +// what do you find +// +// ** your answer here ** +// step through one complete iteration of the loop +// and see how the (Local) Variables are updated +// can you foresee what will eventually happen? +// ** place your answer here ** +// +// commit your answers (bare0_1) +// +// 2. alter the constant X_INIT so that `x += 1` directly causes `x` to wrap +// what happens when `x` wraps +// ** your answer here ** +// +// commit your answers (bare0_2) +// +// 3. place a breakpoint at `x += 1` +// change (both) += opertions to use wrapping_add +// load and run the progam, what happens +// ** your answer here ** +// +// now continue exectution, what happens +// ** your answer here ** +// +// commit your answers (bare0_3) +// +// (if the program did not succeed back to the breakpoint +// you have some fault in the program and go back to 3) +// +// 4. change the asserion to `assert!(x == X && X == Y + 1)`, what happens +// ** place your answer here ** +// +// commit your answers (bare0_4) +// +// 5. remove the assertion and +// +// make "safe" functions for reading and writing X and Y +// e.g. read_x, read_y, write_x, write_y +// +// rewrite the program to use ONLY "safe" code besides the +// read/write functions (which are internally "unsafe") +// +// commit your solution (bare0_5) +// +// 6*. optional +// implement a read_u32/write_u32, taking a reference to a +// "static" variable +// +// rewrite the program to use this abstraction instead of "read_x", etc. +// +// commit your solution (bare0_6) +// +