timer working
This commit is contained in:
84
time_meas/src/bin/main.rs
Normal file
84
time_meas/src/bin/main.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
// src/bin/main.rs
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::pac;
|
||||
use embassy_stm32::interrupt::InterruptExt;
|
||||
use embassy_stm32::timer::low_level::{CountingMode, Timer as LLTimer};
|
||||
use embassy_stm32::time::khz;
|
||||
use embassy_stm32::interrupt;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
// Pointer to the local `counter` so the ISR can read it with zero per-iteration overhead.
|
||||
static COUNTER_PTR: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
// NVIC handler for TIM2
|
||||
#[interrupt]
|
||||
fn TIM2() {
|
||||
// Clear UIF, stop the timer
|
||||
pac::TIM2.sr().modify(|r| r.set_uif(false));
|
||||
pac::TIM2.cr1().modify(|r| r.set_cen(false));
|
||||
|
||||
// Snapshot the counter that the loop has been incrementing
|
||||
let ptr = COUNTER_PTR.load(Ordering::Relaxed) as *const u32;
|
||||
let count = unsafe { core::ptr::read_volatile(ptr) };
|
||||
|
||||
info!("10 seconds elapsed, counter = {}", count);
|
||||
|
||||
// Halt
|
||||
loop {
|
||||
cortex_m::asm::bkpt();
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
info!("Start");
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
// Configure TIM2
|
||||
let mut tim2 = LLTimer::new(p.TIM2);
|
||||
tim2.stop();
|
||||
tim2.set_counting_mode(CountingMode::EdgeAlignedUp);
|
||||
|
||||
// Make the timer tick at 10 kHz. Driver derives PSC from RCC, so timing is exact.
|
||||
tim2.set_tick_freq(khz(10));
|
||||
|
||||
// 10 seconds => 10_000 ticks/s * 10 s = 100_000 ticks. ARR is inclusive: set to 100_000 - 1.
|
||||
tim2.set_max_compare_value(100_000 - 1);
|
||||
|
||||
// One-pulse mode (auto-stop after the first update event)
|
||||
tim2.regs_core().cr1().modify(|r| r.set_opm(true));
|
||||
|
||||
// Ensure no pending UIF from the UG we generated during PSC/ARR programming.
|
||||
// Important: do this BEFORE enabling UIE/NVIC to avoid an immediate ISR.
|
||||
let _ = tim2.clear_update_interrupt();
|
||||
|
||||
// Enable update interrupt, reset counter to 0. Do not start yet.
|
||||
tim2.enable_update_interrupt(true);
|
||||
tim2.reset();
|
||||
|
||||
// Expose the address of the loop counter BEFORE enabling the NVIC so the ISR
|
||||
// never runs before COUNTER_PTR is valid.
|
||||
let mut counter: u32 = 0;
|
||||
COUNTER_PTR.store(&counter as *const u32 as usize, Ordering::Relaxed);
|
||||
|
||||
// Unpend and enable NVIC for TIM2, then start the timer.
|
||||
unsafe {
|
||||
embassy_stm32::interrupt::TIM2.unpend();
|
||||
embassy_stm32::interrupt::TIM2.enable();
|
||||
}
|
||||
tim2.start();
|
||||
|
||||
// Tight CPU loop for benchmarking
|
||||
loop {
|
||||
counter = counter.wrapping_add(1);
|
||||
|
||||
if counter % 10000 == 0 {
|
||||
info!("CPU doing other work: {}", counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
time_meas/src/lib.rs
Normal file
1
time_meas/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
||||
#![no_std]
|
||||
Reference in New Issue
Block a user