Select Git revision
gen-examples.sh
Forked from
KLEE / cortex-m-rtfm-klee
Source project has a limited visibility.
-
Jorge Aparicio authoredJorge Aparicio authored
bare0.rs 3.48 KiB
//! 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;
use core::cell::UnsafeCell;
struct U32 {
data: UnsafeCell<u32>,
}
// a constant (cannot be changed at run-time)
const X_INIT: u32 = 0xffffffff;
// global mutabale variables (changed using unsafe code)
static X: U32 = U32 {
data: UnsafeCell::new(X_INIT),
};
static Y: U32 = U32 {
data: UnsafeCell::new(0),
};
unsafe impl Sync for U32 {}
#[entry]
fn main() -> ! {
// local mutabale variable (changed in safe code)
let mut x = read_u32(&X);
loop {
x = x.wrapping_add(1); // <- place breakpoint here (3)
write_u32(&X, read_u32(&X).wrapping_add(1) );
write_u32(&Y, read_u32(&X));
assert!(x == read_u32(&X) && read_u32(&X) == read_u32(&Y) );
}
}
fn read_u32(uint: &U32) -> u32 {
return unsafe{ *uint.data.get()};
}
fn write_u32(write_to: &U32, value: u32) {
unsafe{ *write_to.data.get() = value };
}
// 0. Compile/build the example in debug (dev) mode.
//
// > cargo build --example bare0
// (or use the vscode build task)
//
// 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.
//
// *** x: 962669 ***
//
// In the Expressions (WATCH -vscode) view add X and Y
// what do you find
//
// *** Watch X and Y didn't work, added watch to 'bare0::X::h2583a8be644794f3' and 'bare0::Y::hef3986a5288bec08' to be able to read the variables
// X = 962669, Y = 962668 ***
//
// Step through one complete iteration of the loop
// and see how the (Local) Variables are updated
// can you foresee what will eventually happen?
//
// *** x is incremented. Eventually x will wrap. ***
//
// 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
//
// ** We end up in the panic handler **
//
// 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
// ** x value wraps around u32 max 4294967295 and get value 0**
//
// Now continue exectution, what happens
// ** X,Y and x is incremented and wraps around max **
//
// 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?
//
// ** The assert fails and we go into panic handler **
//
// Commit your answers (bare0_4)
//
// 5. Remove the assertion and implement "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)
//