Select Git revision
-
Per Lindgren authoredPer Lindgren authored
rtic_bare3.rs 3.98 KiB
//! rtic_bare3.rs
//!
//! Measuring execution time
//!
//! What it covers
//! - Reading Rust documentation
//! - Timing abstractions and semantics
//! - Understanding Rust abstractions
#![no_main]
#![no_std]
use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
use rtic::cyccnt::Instant;
use stm32f4;
#[rtic::app(device = stm32f4)]
const APP: () = {
#[init]
fn init(mut cx: init::Context) {
cx.core.DWT.enable_cycle_counter();
let start = Instant::now();
wait(1_000_000);
let end = Instant::now();
// notice all printing outside of the section to measure!
hprintln!("Start {:?}", start).ok();
hprintln!("End {:?}", end).ok();
// hprintln!("Diff {:?}", (end - start) ).ok();
}
};
// burns CPU cycles by just looping `i` times
#[inline(never)]
#[no_mangle]
fn wait(i: u32) {
for _ in 0..i {
// no operation (ensured not optimized out)
cortex_m::asm::nop();
}
}
// 0. Setup
//
// > cargo doc --open
//
// In the docs, search (`S`) for `Monotonic` and read the API docs.
// Also search for `Instant`, and `Duration`.
//
// Together these provide timing semantics.
//
// - `Monotonic` is a "trait" for a timer implementation.
// - `Instant` is a point in time.
// - `Duration` is a range in time.
//
// By default RTIC uses the `Systic` and the `DWT` cycle counter
// to provide a `Monotonic` timer.
//
// 1. Build and run the application in vscode using (Cortex Release).
//
// What is the output in the Adapter Output console?
//
// ** your answer here **
//
// As you see line 31 is commented out (we never print the difference).
//
// Now uncomment line 31, and try to run the program. You will see
// that it fails to compile right as `Duration` does not implement `Debug`
// (needed for formatting the printout.)
//
// This is on purpose as `Duration` is abstract (opaque). You need to
// turn it into a concrete value. Look at the documentation, to find out
// a way to turn it into clock cycles (which are printable).
//
// What is now the output in the Adapter Output console?
//
// ** your answer here **
//
// Commit your answers (bare3_1)
//
// 2. Look at the `Instant` documentation.
//
// Alter the code so that you use `duration_since`, instead of manual subtraction.
//
// What is now the output in the Adapter Output console?
//
// ** your answer here **
//
// Commit your answers (bare3_2)
//
// 3. Look at the `Instant` documentation.
// Now alter the code so that it uses `elapsed` instead.
//
// What is now the output in the Adapter Output console?
//
// ** your answer here **
//
// Commit your answers (bare3_3)
//
// 4. Discussion.
//
// If you did implement the above exercises correctly you should get exactly the same
// result (in clock cycles) for all cases as you got in the bare2 exercise.
// (If not, go back and revise your code.)
//
// What this shows, is that we can step away from pure hardware accesses
// and deal with time in a more convenient and "abstract" fashion.
//
// `Instant` and `Duration` are associated with semantics (meaning).
// `Monotonic` is associated the implementation.
//
// This is an example of separation of concerns!
//
// If you implement your application based on Instant and Duration, your code
// will be "portable" across all platforms (that implement Monotonic).
//
// The implementation of Monotonic is done only once for each platform, thus
// bugs related to low level timer access will occur only at one place,
// not scattered across thousands of manually written applications.
//
// However, as you have already seen, the current time abstraction (API) is
// is rather "thin" (provided just a bare minimum functionality).
//
// We are working to further generalize timing semantics, by building
// on a richer abstraction `https://docs.rs/embedded-time/0.10.1/embedded_time/`.
//
// Support for embedded time is projected for next RTIC release.