Select Git revision
bare0.rs 3.94 KiB
//! bare0.rs
//! Simple bare metal application
// feature to ensure symbols to be linked
#![feature(used)]
// build without the Rust standard library
#![no_std]
use core::u32;
// Minimal runtime / startup for Cortex-M microcontrollers
extern crate cortex_m_rt;
const X_INIT: u32 = u32::MAX;
static mut X: u32 = X_INIT;
static mut Y: u32 = 0;
#[inline(never)]
fn main() {
let mut x = read_x();
loop {
x = x.wrapping_add(1);
write_x(read_x().wrapping_add(1));
write_y(read_x());
}
}
fn write_y(y: u32) {
unsafe {
Y = y;
}
}
fn read_x() -> u32 {
unsafe { X }
}
fn write_x(x: u32) {
unsafe {
X = x;
}
}
// 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
//
// (gdb) info locals
// x = 6686607
//
// in the Expressions (WATCH -vscode) view add X and Y
// what do you find
//
// (gdb) print X
// $19 = 6686606
// (gdb) print Y
// $20 = 6686606
//
// step through one complete iteration of the loop
// and see how the (Local) Variables are updated
// can you foresee what will eventually happen?
//
// The unsigned 32 bit variable will eventually overflow.
//
// commit your answers (bare0_1)
//
// 2. alter the constant X_INIT so that line 22 directly causes the x to wrap
// what happens when x wraps
//
// (gdb) print x
// $1 = 4294967295
// (gdb) next
//
// Program received signal SIGTRAP, Trace/breakpoint trap.
// cortex_m_rt::default_handler (ef=0x20017e68) at /home/kitzin/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.3.12/src/lib.rs:454
// 454 asm::bkpt();
//
// Overflow is detected and program !panics
//
// commit your answers (bare0_2)
//
// 3. change += opertions to wrapping_add
// place a breakpoint at line 22
// load and run the progam, what happens
//
// Breakpoint 2, bare0::main () at examples/bare0.rs:24
// 24 x = x.wrapping_add(1);
// (gdb) print x
// $55 = 4294967295
// (gdb) next
// 26 X += 1;
// (gdb) print x
// $56 = 0
//
// now continue exectution, what happens
//
// (gdb) print bare0::X
// $69 = 4294967295
// (gdb) next
// 27 Y = X;
// (gdb) print bare0::X
// $70 = 0
// (gdb) c
// Continuing.
//
// Breakpoint 2, bare0::main () at examples/bare0.rs:24
// 24 x = x.wrapping_add(1);
//
// commit your answers (bare0_3)
//
// (if the program did not succed 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
//
// (gdb) next
// 28 assert!(x == X && X == Y + 1);
// (gdb) next
//
// Program received signal SIGTRAP, Trace/breakpoint trap.
// cortex_m_rt::default_handler (ef=0x20017e60) at /home/kitzin/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.3.12/src/lib.rs:454
// 454 asm::bkpt();
// (gdb) print bare0::X
// $72 = 0
// (gdb) print bare0::Y
// $73 = 0
//
//
// The assert condition (0 == 1) is false and it !panics
//
//
// 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)
//
// As we are not using interrupts, we just register a dummy catch all handler
#[link_section = ".vector_table.interrupts"]
#[used]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
extern "C" fn default_handler() {
loop {}
}