diff --git a/examples/bare4.rs b/examples/bare4.rs index 0dd033ee0ef6e99f87e734ee81b08faaf3abed1a..6fc12521306057ceed2e3c47854d2d523fc553fb 100644 --- a/examples/bare4.rs +++ b/examples/bare4.rs @@ -28,6 +28,7 @@ use address::*; #[inline(always)] fn read_u32(addr: u32) -> u32 { unsafe { core::ptr::read_volatile(addr as *const _) } + //core::ptr::read_volatile(addr as *const _) } #[inline(always)] @@ -44,11 +45,11 @@ fn wait(i: u32) { } fn main() { - // power on GPIOA, RM0368 6.3.11 + // power on GPIOA let r = read_u32(RCC_AHB1ENR); // read write_u32(RCC_AHB1ENR, r | 1); // set enable - // configure PA5 as output, RM0368 8.4.1 + // configure PA5 as output let r = read_u32(GPIOA_MODER) & !(0b11 << (5 * 2)); // read and mask write_u32(GPIOA_MODER, r | 0b01 << (5 * 2)); // set output mode @@ -56,16 +57,59 @@ fn main() { // this is more efficient as the read register is not needed. loop { - // set PA5 high, RM0368 8.4.7 + // set PA5 high write_u32(GPIOA_BSRR, 1 << 5); // set bit, output hight (turn on led) wait(10_000); - // set PA5 low, RM0368 8.4.7 + // set PA5 low write_u32(GPIOA_BSRR, 1 << (5 + 16)); // clear bit, output low (turn off led) wait(10_000); } } +// 1. build and run the application (debug build) +// did you enjoy the blinking? +// ** your answer here ** +// +// now lookup the data-sheets, and read each section referred, +// 6.3.11, 8.4.1, 8.4.7 +// +// document each low level access *code* by the appropriate section in the +// data sheet +// +// commit your answers (bare4_1) +// +// 2. comment out line 30 and uncomment line 31 (essentially omitting the `unsafe`) +// what was the error message and explain why, +// ** your answer here ** +// +// digging a bit deeper, why do you think `read_volatile` is declared `unsafe` +// (https://doc.rust-lang.org/core/ptr/fn.read_volatile.html, for some food for thought ) +// ** your answer here ** +// +// commit your answers (bare4_2) +// +// 3. +// volatile read/writes are explicit *volatile operations* in Rust, while in C they +// are declared at type level (i.e., access to varibles declared volatile amounts to +// volatile reads/and writes) +// +// both C and Rust (even more) allows code optimization to re-order operations, as long +// as data dependencies are preserved. +// +// why is important that ordering of volatile operations are ensured by the compiler? +// ** your answer here ** +// +// give an example in the above code, where reordering might make things go horribly wrong +// (hint, accessing a peripheral not being powered...) +// ** your answer here ** +// +// without the non-reording proprety of `write_volatile/read_volatile` could that happen in theory +// (argue from the point of data dependencies) +// ** your answer here ** +// +// commit your answers (bare4_3) + // As we are not using interrupts, we just register a dummy catch all handler #[link_section = ".vector_table.interrupts"] #[used]