diff --git a/examples/timing_exam.rs b/examples/timing_exam.rs new file mode 100644 index 0000000000000000000000000000000000000000..b4f7c5821ecf456e281e70bb96bd74e19bca8cb1 --- /dev/null +++ b/examples/timing_exam.rs @@ -0,0 +1,99 @@ +//! examples/timing_exam.rs + +// #![deny(unsafe_code)] +// #![deny(warnings)] +#![no_main] +#![no_std] + +use cortex_m::{asm, peripheral::DWT}; +use panic_halt as _; +use stm32f4::stm32f411; +use rtic::cyccnt::{Instant, Duration, U32Ext}; + +#[rtic::app(device = stm32f411, monotonic = rtic::cyccnt::CYCCNT)] +const APP: () = { + struct Resources { + #[init(0)] + R1: u64, // non atomic data + #[init(0)] + R2: u64, // non atomic data + } + + #[init(schedule = [t1, t2, t3])] + fn init(mut cx: init::Context) { + // Initialize (enable) the monotonic timer (CYCCNT) + cx.core.DCB.enable_trace(); + cx.core.DWT.enable_cycle_counter(); + // cx.schedule.t1(cx.start).unwrap(); + // cx.schedule.t2(cx.start).unwrap(); + // cx.schedule.t3(cx.start).unwrap(); + } + + // Deadline 100, Inter-arrival 100 + #[task(schedule = [t1], priority = 1)] + fn t1(cx: t1::Context) { + // 1) your code here to emulate timing behavior of t1 + + // 2) your code here to check for overrun + cx.schedule.t1(cx.scheduled + 100_000.cycles()).unwrap(); + } + + // Deadline 200, Inter-arrival 200 + #[task(schedule = [t2], resources = [R1, R2], priority = 2)] + fn t2(cx: t2::Context) { + // 1) your code here to emulate timing behavior of t2 + + // 2) your code here to check for overrun + cx.schedule.t2(cx.scheduled + 200_000.cycles()).unwrap(); + } + + // Deadline 50, Inter-arrival 50 + #[task(schedule = [t3], resources = [R2], priority = 3)] + fn t3(cx: t3::Context) { + // 1) your code here to emulate timing behavior of t3 + + // 2) your code here to check for overrun + cx.schedule.t3(cx.scheduled + 50_000.cycles()).unwrap(); + } + + // RTIC requires that unused interrupts are declared in an extern block when + // using software tasks; these free interrupts will be used to dispatch the + // software tasks. + extern "C" { + fn EXTI0(); + fn EXTI1(); + fn EXTI2(); + } +}; + +fn delay_duration(from: Instant, until: Duration) { + // implement a delay that busy waits for a Duration of time + // Use `cargo doc` to generate documentation to lookup `Duration` + // and `Instance` and corresponding operations and conversions. + // + // In particular, the `elapsed` is useful. + // Notice you can compare durations. +} + +// 1) For this assignment you should first generate a task set that +// matches the example task set from `klee_tutorial/srp_analysis/main.rs`. +// +// The task set should have the same relative timing properties as given in `main.rs`. +// +// Assume that each time unit amounts to 1_000 clock cycles, then +// the execution time of `t1` should be 10_000 clock cycles. +// +// To emulate corresponding workload you should implement `delay_duration` +// and use that to get the relative timings. +// +// So, instead of measuring execution time of an existing application, you are to create +// one with given timing properties. +// +// To verify that you have implemented the tasks correctly you should trigger them +// one at a time, put breakpoints at each point of interest and check the CYCCNT manually. +// +// (Verify the timing properties for each task separately.) +// +// Commit your repository once you have done all validation. +// +// 2) \ No newline at end of file