Skip to content
Snippets Groups Projects
Select Git revision
  • a5f08ad436ee3154b839953974765d0d781030f7
  • master default protected
2 results

bare0.rs

Blame
  • 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 {}
    }