diff --git a/examples/bare5.rs b/examples/bare5.rs index be4f6373c44dde82a025bcbd6c6f6aacaf85d2f0..21957f7736d1e90b9f4bb67e6456ede1255c2f8a 100644 --- a/examples/bare5.rs +++ b/examples/bare5.rs @@ -13,6 +13,7 @@ extern crate panic_halt; extern crate cortex_m; use cortex_m_rt::entry; +use cortex_m_semihosting::{hprint, hprintln}; // C like API... mod stm32f40x { @@ -56,13 +57,21 @@ mod stm32f40x { // offset (field offset) // width (field width) // value (new value that the field should take) - // - // impl VolatileCell<u32> { - // #[inline(always)] - // pub fn modify(&self, offset: u8, width: u8, value: u32) { - // // your code here - // } - // } + impl VolatileCell<u32> { + #[inline(always)] + pub fn modify(&self, offset: u8, width: u8, value: u32) { + let mask: u32 = 2u32.pow(width as u32) - 1; // 'width' amount of binary 1s. + + // Mask the input + let in_masked: u32 = value & mask; + + // Mask the previous value + let previous: u32 = self.read(); + let previous_masked: u32 = previous & !(mask * 2u32.pow(offset as u32)); + + self.write(previous_masked | (in_masked * 2u32.pow(offset as u32))); + } + } #[repr(C)] #[allow(non_snake_case)] @@ -141,27 +150,29 @@ fn wait(i: u32) { } // simple test of Your `modify` -//fn test() { -// let t:VolatileCell<u32> = unsafe { core::mem::uninitialized() }; -// t.write(0); -// assert!(t.read() == 0); -// t.modify(3, 3, 0b10101); -// // -// // 10101 -// // ..0111000 -// // --------- -// // 000101000 -// assert!(t.read() == 0b101 << 3); -// t.modify(4, 3, 0b10001); -// // 000101000 -// // 111 -// // 001 -// // 000011000 -// assert!(t.read() == 0b011 << 3); - -// if << is used, your code will panic in dev (debug), but not in release mode -// t.modify(32, 3, 1); -//} +// fn test() { +// let t:VolatileCell<u32> = unsafe { core::mem::uninitialized() }; +// t.write(0); +// assert!(t.read() == 0); +// t.modify(3, 3, 0b10101); +// // +// // 10101 +// // ..0111000 +// // --------- +// // 000101000 +// hprintln!("{:b}", t.read()).unwrap(); +// assert!(t.read() == 0b101 << 3); +// t.modify(4, 3, 0b10001); +// // 000101000 +// // 111 +// // 001 +// // 000011000 +// hprintln!("{:b}", t.read()).unwrap(); +// assert!(t.read() == 0b011 << 3); + +// // if << is used, your code will panic in dev (debug), but not in release mode +// t.modify(32, 3, 1); +// } // system startup, can be hidden from the user #[entry] @@ -177,23 +188,40 @@ fn main() -> ! { // user application fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) { // power on GPIOA - let r = rcc.AHB1ENR.read(); // read - rcc.AHB1ENR.write(r | 1 << (0)); // set enable + rcc.AHB1ENR.modify(0u8, 1u8, 1u32); + // let r = rcc.AHB1ENR.read(); // read + // rcc.AHB1ENR.write(r | 1 << (0)); // set enable // configure PA5 as output - let r = gpioa.MODER.read() & !(0b11 << (5 * 2)); // read and mask - gpioa.MODER.write(r | 0b01 << (5 * 2)); // set output mode - + gpioa.MODER.modify(10u8, 2u8, 1u32); + // let r = gpioa.MODER.read() & !(0b11 << (5 * 2)); // read and mask + // gpioa.MODER.write(r | 0b01 << (5 * 2)); // set output mode + let led_odr = &gpioa.ODR; loop { // set PA5 high +<<<<<<< HEAD // gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led) gpioa.ODR.write(gpioa.ODR.read() | (1 << 5)); +======= + // gpioa.ODR.modify(5u8, 1u8, 1u32); + led_odr.modify(5u8, 1u8, 1u32); + + // gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led) + // gpioa.ODR.write(gpioa.ODR.read() | (1 << 5)); +>>>>>>> student-1 wait(10_000); // set PA5 low +<<<<<<< HEAD // gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led) gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5)); +======= + // gpioa.ODR.modify(5u8, 1u8, 0u32); + led_odr.modify(5u8, 1u8, 0u32); + // gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led) + // gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5)); +>>>>>>> student-1 wait(10_000); } } @@ -243,3 +271,10 @@ fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) { // Notice, over-shifting (where bits are spilled) is always considered legal, // its just the shift amuount that is checked. // There are explicit unchecked versions available if so wanted. +// +// ** ORDERING IS WRONG FOR OPTIMIZED CODE ** +// When I run the --release build, the LED is constantly turned on. HOWEVER, +// if I set breakpoints and pause in the --release build, I can pause it +// just after the LED-turn-off call and the LED turns off, proving that the +// instructions work in release as they do in debug, but that it doesn't wait +// before running the turn-on call as it should. \ No newline at end of file diff --git a/examples/bare7.rs b/examples/bare7.rs index ecf0fbb104a9443c9c469e8e5f985c6bb620f338..f69c655a37727dadf38b8c53a6e80ce47c548d19 100644 --- a/examples/bare7.rs +++ b/examples/bare7.rs @@ -125,11 +125,12 @@ fn main() -> ! { // // rcc.cfgr.sysclk(64.mhz()).pclk1(64.mhz()).pclk2(64.mhz()).freeze(); // -// ** your answer here ** +// ** PCLK1 must be lower than 42 MHz. ** // // rcc.cfgr.sysclk(84.mhz()).pclk1(42.mhz()).pclk2(64.mhz()).freeze(); // -// ** your answer here ** +// ** With sysclk at 84 MHz, it is impossible to get PCLK2 at 64 MHz with only a +// prescaler that divides by integer values. Closest PCLK2 are 84 MHz and 42 MHz. ** // // Commit your answers (bare7_1) //