diff --git a/examples/bare1.rs b/examples/bare1.rs index 3b5de813553fc4e8a0833216010a27a1f335d0ff..4a8fbc20d34572309f9d2815c76b1068252c62bc 100644 --- a/examples/bare1.rs +++ b/examples/bare1.rs @@ -6,7 +6,7 @@ //! - tracing over semihosting and ITM //! - assembly calls and inline assembly //! - more on arithmetics -//! --- +//! #![no_main] #![no_std] diff --git a/examples/bare2.rs b/examples/bare2.rs index d68edd2e155eca87e19a5dae2127c85aefab56e7..3986dccc7ab777b6533dcc6d53fb5f1678777652 100644 --- a/examples/bare2.rs +++ b/examples/bare2.rs @@ -17,6 +17,7 @@ use cortex_m::{iprintln, peripheral::DWT, Peripherals}; use cortex_m_rt::entry; // burns CPU cycles by just looping `i` times +#[inline(never)] fn wait(i: u32) { for _ in 0..i { // no operation (ensured not optimized out) diff --git a/examples/bare3.rs b/examples/bare3.rs index cb56630cbbe5588ec9884d4cf07db1e3ac9ee917..f1ce59b3f153f24c519440dbb53f34bed7da3804 100644 --- a/examples/bare3.rs +++ b/examples/bare3.rs @@ -91,7 +91,7 @@ fn main() -> ! { // commit your answers (bare3_4) // // 5. Look for a way to make this copy done without a loop. -// https://doc.rust-lang.org/beta/std/primitive.slice.html +// https://doc.rust-lang.org/std/primitive.slice.html // // Implement and test your solution. // diff --git a/examples/bare4.rs b/examples/bare4.rs index 724f355307b1c1adb098170a7c0b0d6757ffb194..b5f1d5aebc996fca28036ca54f17293071e54e2d 100644 --- a/examples/bare4.rs +++ b/examples/bare4.rs @@ -87,11 +87,11 @@ fn main() -> ! { // 6.3.11, 8.4.1, 8.4.7 // // Document each low level access *code* by the appropriate section in the -// data sheet +// data sheet. // // commit your answers (bare4_1) // -// 2. comment out line 40 and uncomment line 41 (essentially omitting the `unsafe`) +// 2. Comment out line 40 and uncomment line 41 (essentially omitting the `unsafe`) // // //unsafe { core::ptr::read_volatile(addr as *const _) } // core::ptr::read_volatile(addr as *const _) diff --git a/examples/bare5.rs b/examples/bare5.rs index b55ee6b7a36cc0df8b00b9574e47359c233e6b54..3600a6816bb4efd817df3baa404337997fd4df71 100644 --- a/examples/bare5.rs +++ b/examples/bare5.rs @@ -4,7 +4,7 @@ //! //! What it covers: //! - abstractions in Rust -//! +//! - structs and implementations #![feature(uniform_paths)] // requires nightly #![no_std] diff --git a/examples/bare6.rs b/examples/bare6.rs index 0ad8102bd240b3b8b3b029c70b9f9935055aa0df..c9ad65b4b47db2eaaacdef5aad922ede044e5a71 100644 --- a/examples/bare6.rs +++ b/examples/bare6.rs @@ -3,34 +3,21 @@ //! Clocking //! //! What it covers: +//! - using svd2rust generated API //! - setting the clock via script (again) //! - routing the clock to a PIN for monitoring by an oscilloscope //! - changing the clock using Rust code //! -// #![feature(used)] -// #![no_std] - -// extern crate f4; -// extern crate stm32f40x; - -// #[macro_use] -// extern crate cortex_m_debug; -// use f4::clock; -// use f4::prelude::*; -// use stm32f40x::{DWT, FLASH, GPIOA, GPIOC, RCC}; - #![no_main] #![no_std] -#![feature(uniform_paths)] extern crate panic_halt; use cortex_m::{iprintln, peripheral::itm::Stim}; use cortex_m_rt::entry; -use stm32f4::stm32f413; -use stm32f413::{DWT, GPIOA, GPIOC, RCC}; +use stm32f4::stm32f413::{self, DWT, GPIOA, GPIOC, RCC}; #[entry] fn main() -> ! { @@ -65,7 +52,7 @@ fn idle(stim: &mut Stim, rcc: RCC, gpioa: GPIOA) { gpioa.moder.modify(|_, w| w.moder5().bits(1)); // at 16 Mhz, 8_000_000 cycles = period 0.5s - // at 64 Mhz, 4*8_000_000 cycles = period 0.55s + // at 64 Mhz, 4*8_000_000 cycles = period 0.5s // let cycles = 8_000_000; let cycles = 4 * 8_000_000; @@ -99,7 +86,8 @@ fn clock_out(rcc: &RCC, gpioc: &GPIOC) { // mco2 : SYSCLK = 0b00 // mcopre : divide by 4 = 0b110 rcc.cfgr - .modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) }); + //.modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) }); + .modify(|_, w| w.mco2().sysclk().mco2pre().div4()); // power on GPIOC, RM0368 6.3.11 rcc.ahb1enr.modify(|_, w| w.gpiocen().set_bit()); @@ -109,12 +97,15 @@ fn clock_out(rcc: &RCC, gpioc: &GPIOC) { // AF0, gpioc reset value = AF0 // configure PC9 as alternate function 0b10, RM0368 6.2.10 - gpioc.moder.modify(|_, w| w.moder9().bits(0b10)); + gpioc.moder.modify(|_, w| w.moder9().alternate()); + // gpioc.moder.modify(|_, w| w.moder9().bits(0b10)); // otyper reset state push/pull, in reset state (don't need to change) - // ospeedr 0b11 = high speed - gpioc.ospeedr.modify(|_, w| w.ospeedr9().bits(0b11)); + // ospeedr 0b11 = very high speed + + // gpioc.ospeedr.modify(|_, w| w.ospeedr9().bits(0b11)); + gpioc.ospeedr.modify(|_, w| w.ospeedr9().very_high_speed()) } // 1. Compile and run the example, in 16Mhz diff --git a/examples/bare6_nightly.rs b/examples/bare6_nightly.rs new file mode 100644 index 0000000000000000000000000000000000000000..6025e7ebe66cb38d547f6a7b463b814e480f1594 --- /dev/null +++ b/examples/bare6_nightly.rs @@ -0,0 +1,188 @@ +//! bare6.rs +//! +//! Clocking +//! +//! What it covers: +//! - using svd2rust generated API +//! - setting the clock via script (again) +//! - routing the clock to a PIN for monitoring by an oscilloscope +//! - changing the clock using Rust code +//! + +#![no_main] +#![no_std] +#![feature(uniform_paths)] +#![feature(type_alias_enum_variants)] + +extern crate panic_halt; + +use cortex_m::{iprintln, peripheral::itm::Stim}; +use cortex_m_rt::entry; + +use stm32f4::stm32f413; +use stm32f413::{DWT, GPIOA, GPIOC, RCC}; + +#[entry] +fn main() -> ! { + let p = stm32f413::Peripherals::take().unwrap(); + let mut c = stm32f413::CorePeripherals::take().unwrap(); + + let stim = &mut c.ITM.stim[0]; + iprintln!(stim, "Hello, bare6!"); + + c.DWT.enable_cycle_counter(); + unsafe { + c.DWT.cyccnt.write(0); + } + let t = DWT::get_cycle_count(); + iprintln!(stim, "{}", t); + + clock_out(&p.RCC, &p.GPIOC); + // clock::set_84_mhz(rcc, flash); + idle(stim, p.RCC, p.GPIOA); + + loop {} +} + +// // user application +fn idle(stim: &mut Stim, rcc: RCC, gpioa: GPIOA) { + iprintln!(stim, "idle"); + + // power on GPIOA, RM0368 6.3.11 + rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); + + // configure PA5 as output, RM0368 8.4.1 + gpioa.moder.modify(|_, w| w.moder5().bits(1)); + + // at 16 Mhz, 8_000_000 cycles = period 0.5s + // at 64 Mhz, 4*8_000_000 cycles = period 0.5s + // let cycles = 8_000_000; + let cycles = 4 * 8_000_000; + + loop { + iprintln!(stim, "on {}", DWT::get_cycle_count()); + // set PA5 high, RM0368 8.4.7 + gpioa.bsrr.write(|w| w.bs5().set_bit()); + wait_cycles(cycles); + + iprintln!(stim, "off {}", DWT::get_cycle_count()); + // set PA5 low, RM0368 8.4.7 + gpioa.bsrr.write(|w| w.br5().set_bit()); + wait_cycles(cycles); + } +} + +// uses the DWT.CYCNT +// doc: ARM trm_100166_0001_00_en.pdf, chapter 9.2 +// we use the `cortex-m` abstraction, as re-exported by the stm32f40x +fn wait_cycles(nr_cycles: u32) { + let t = DWT::get_cycle_count().wrapping_add(nr_cycles); + while (DWT::get_cycle_count().wrapping_sub(t) as i32) < 0 {} +} + +// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf) +// rcc, chapter 6 +// gpio, chapter 8 +fn clock_out(rcc: &RCC, gpioc: &GPIOC) { + // output MCO2 to pin PC9 + + // mco2 : SYSCLK = 0b00 + // mcopre : divide by 4 = 0b110 + rcc.cfgr + .modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) }); + + // power on GPIOC, RM0368 6.3.11 + rcc.ahb1enr.modify(|_, w| w.gpiocen().set_bit()); + + // MCO_2 alternate function AF0, STM32F401xD STM32F401xE data sheet + // table 9 + // AF0, gpioc reset value = AF0 + + // configure PC9 as alternate function 0b10, RM0368 6.2.10 + gpioc.moder.modify(|_, w| w.moder9().bits(0b10)); + + // otyper reset state push/pull, in reset state (don't need to change) + + // ospeedr 0b11 = high speed + // use stm32f4::stm32f413::gpiof::ospeedr::OSPEEDR9W; + // use gpioc::ospeedr::OSPEEDR9W; + // use stm32f4::stm32f413::gpiof as gpioc; + // use stm32f4::stm32f413::gpiof::ospeedr::OSPEEDR9W::*; + // gpioc.ospeedr.modify(|_, w| w.ospeedr9().bits(0b11)); + // gpioc.ospeedr.modify(|_, w| { + // w.ospeedr9().variant(gpioc::ospeedr::OSPEEDR9W::HIGHSPEED) + // }); + + // gpioc.ospeedr.modify(|_, w| w.ospeedr9().low_speed()) + gpioc.ospeedr.modify(|_, w| w.ospeedr9().very_high_speed()) +} + +// 1. Compile and run the example, in 16Mhz +// The processor SYSCLK defaults to HCI 16Mhz +// (this is what you get after a `monitor reset halt`). +// +// Confirm that your ITM dump traces the init, idle and led on/off. +// Make sure your TPIU is set to a system clock at 16Mhz +// +// What is the frequency of blinking? +// +// ** your answer here ** +// +// commit your answers (bare6_1) +// +// 2. Now connect an oscilloscope to PC9, which is set to +// output the MCO2. +// +// What is the frequency of MCO2 read by the oscilloscope? +// +// ** your answer here ** +// +// Compute the value of SYSCLK based on the oscilloscope reading +// +// ** your answer here ** +// +// What is the peak to peak reading of the signal? +// +// ** your answer here ** +// +// Make a folder called "pictures" in your git project. +// Make a screen dump or photo of the oscilloscope output. +// Save the the picture as "bare_6_16mhz_high_speed". +// +// commit your answers (bare6_2) +// +// 3. Now run the example in 64Mz +// You can do that by issuing a `monitor reset init` +// which reprograms SYSCLK to 4*HCI. +// +// +// Confirm that your ITM dump traces the init, idle and led on/off +// (make sure your TPIU is set to a system clock at 64Mhz) +// +// Uncommnet: `let cycles = 4 * 8_000_000; +//` +// What is the frequency of blinking? +// +// ** your answer here ** +// +// commit your answers (bare6_3) +// +// 4. Repeat experiment 2 +// +// What is the frequency of MCO2 read by the oscilloscope? +// +// ** your answer here ** +// +// Compute the value of SYSCLK based on the oscilloscope reading. +// +// ** your answer here ** +// +// What is the peak to peak reading of the signal? +// +// ** your answer here ** +// +// Make a screen dump or photo of the oscilloscope output. +// Save the the picture as "bare_6_64mhz_high_speed". +// +// commit your answers (bare6_4) +//