Skip to main content

embedded_3dgfx/
hardware_profile.rs

1use core::sync::atomic::{AtomicU32, Ordering};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum TraceTransport {
5    None,
6    #[cfg(feature = "rtt-trace")]
7    Rtt,
8    #[cfg(feature = "itm-trace")]
9    Itm,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct CycleSample {
14    pub label: &'static str,
15    pub cycles: u32,
16}
17
18static LAST_SAMPLE_CYCLES: AtomicU32 = AtomicU32::new(0);
19
20#[cfg(all(feature = "dwt-profiler", target_arch = "arm"))]
21const DEMCR: *mut u32 = 0xE000_EDFC as *mut u32;
22#[cfg(all(feature = "dwt-profiler", target_arch = "arm"))]
23const DWT_CTRL: *mut u32 = 0xE000_1000 as *mut u32;
24#[cfg(all(feature = "dwt-profiler", target_arch = "arm"))]
25const DWT_CYCCNT: *mut u32 = 0xE000_1004 as *mut u32;
26
27#[cfg(all(feature = "dwt-profiler", target_arch = "arm"))]
28pub fn init_dwt_cycle_counter() {
29    // SAFETY: Accessing ARM debug registers by fixed address on supported targets.
30    unsafe {
31        let demcr = core::ptr::read_volatile(DEMCR);
32        core::ptr::write_volatile(DEMCR, demcr | (1 << 24));
33        let dwt_ctrl = core::ptr::read_volatile(DWT_CTRL);
34        core::ptr::write_volatile(DWT_CTRL, dwt_ctrl | 1);
35    }
36}
37
38#[cfg(not(all(feature = "dwt-profiler", target_arch = "arm")))]
39pub fn init_dwt_cycle_counter() {}
40
41#[cfg(all(feature = "dwt-profiler", target_arch = "arm"))]
42pub fn read_cycle_counter() -> Option<u32> {
43    // SAFETY: Accessing ARM DWT cycle counter register on supported targets.
44    Some(unsafe { core::ptr::read_volatile(DWT_CYCCNT) })
45}
46
47#[cfg(not(all(feature = "dwt-profiler", target_arch = "arm")))]
48pub fn read_cycle_counter() -> Option<u32> {
49    None
50}
51
52pub fn sample_cycles(label: &'static str, start_cycles: u32, end_cycles: u32) -> CycleSample {
53    let cycles = end_cycles.wrapping_sub(start_cycles);
54    LAST_SAMPLE_CYCLES.store(cycles, Ordering::Relaxed);
55    CycleSample { label, cycles }
56}
57
58pub fn last_sample_cycles() -> u32 {
59    LAST_SAMPLE_CYCLES.load(Ordering::Relaxed)
60}
61
62pub fn emit_trace(_sample: CycleSample) {
63    #[cfg(feature = "rtt-trace")]
64    {
65        #[cfg(feature = "std")]
66        {
67            std::println!(
68                "RTT_TRACE label={} cycles={}",
69                _sample.label,
70                _sample.cycles
71            );
72        }
73    }
74
75    #[cfg(feature = "itm-trace")]
76    {
77        #[cfg(feature = "std")]
78        {
79            std::println!(
80                "ITM_TRACE label={} cycles={}",
81                _sample.label,
82                _sample.cycles
83            );
84        }
85    }
86}