Skip to main content

rlvgl_platform/hwcore/regs/
tim.rs

1//! Typed register layout for the STM32H747 basic timers (TIM6 / TIM7).
2//!
3//! Layout matches RM0399 §43.4 ("TIM6/7 register map"). Basic timers
4//! have a strict subset of the general-purpose / advanced timer
5//! registers — they have no input capture, no output compare, no
6//! complementary outputs. The 747I-DISCO uses TIM6 in the bare-metal
7//! build for the touch-poll cadence and TIM7 in the FreeRTOS build for
8//! the system tick.
9
10use core::mem::offset_of;
11
12use crate::hwcore::addr::MmioAddr;
13use crate::hwcore::regs::access::Rw;
14
15/// MMIO layout of one basic timer (TIM6 / TIM7).
16#[repr(C)]
17pub struct TimBasicRegs {
18    /// `0x00` Control Register 1 (CEN, UDIS, URS, OPM, ARPE).
19    pub cr1: Rw<u32>,
20    /// `0x04` Control Register 2 (MMS).
21    pub cr2: Rw<u32>,
22    /// `0x08..0x0B` reserved.
23    _reserved_08: u32,
24    /// `0x0C` DMA / Interrupt Enable Register (UIE).
25    pub dier: Rw<u32>,
26    /// `0x10` Status Register (UIF flag).
27    pub sr: Rw<u32>,
28    /// `0x14` Event Generation Register (UG).
29    pub egr: Rw<u32>,
30    /// `0x18..0x23` reserved (3 × `u32`).
31    _reserved_18: [u32; 3],
32    /// `0x24` Counter Register.
33    pub cnt: Rw<u32>,
34    /// `0x28` Prescaler Register.
35    pub psc: Rw<u32>,
36    /// `0x2C` Auto-Reload Register.
37    pub arr: Rw<u32>,
38}
39
40const _: () = assert!(offset_of!(TimBasicRegs, cr1) == 0x00);
41const _: () = assert!(offset_of!(TimBasicRegs, cr2) == 0x04);
42const _: () = assert!(offset_of!(TimBasicRegs, dier) == 0x0C);
43const _: () = assert!(offset_of!(TimBasicRegs, sr) == 0x10);
44const _: () = assert!(offset_of!(TimBasicRegs, egr) == 0x14);
45const _: () = assert!(offset_of!(TimBasicRegs, cnt) == 0x24);
46const _: () = assert!(offset_of!(TimBasicRegs, psc) == 0x28);
47const _: () = assert!(offset_of!(TimBasicRegs, arr) == 0x2C);
48
49/// Base address of TIM6 (APB1, used by bare-metal touch poll).
50pub const TIM6_BASE: usize = 0x4000_1000;
51/// Base address of TIM7 (APB1, used by FreeRTOS tick).
52pub const TIM7_BASE: usize = 0x4000_1400;
53
54/// Typed handle on a basic timer.
55pub struct TimBasic {
56    base: MmioAddr<TimBasicRegs>,
57}
58
59impl TimBasic {
60    /// Construct a handle at the given base address.
61    ///
62    /// # Safety
63    ///
64    /// `base` must be [`TIM6_BASE`] or [`TIM7_BASE`]. The timer's
65    /// clock (`RCC.APB1LENR.TIM{6,7}EN`) must be enabled before any
66    /// field is accessed and the timer must be unaliased.
67    pub const unsafe fn new(base: usize) -> Self {
68        // SAFETY: caller contract.
69        Self {
70            base: unsafe { MmioAddr::new(base) },
71        }
72    }
73
74    /// Convenience constructor for TIM6.
75    ///
76    /// # Safety
77    ///
78    /// See [`Self::new`].
79    pub const unsafe fn tim6() -> Self {
80        // SAFETY: address is the silicon-defined TIM6 base.
81        unsafe { Self::new(TIM6_BASE) }
82    }
83
84    /// Convenience constructor for TIM7.
85    ///
86    /// # Safety
87    ///
88    /// See [`Self::new`].
89    pub const unsafe fn tim7() -> Self {
90        // SAFETY: address is the silicon-defined TIM7 base.
91        unsafe { Self::new(TIM7_BASE) }
92    }
93
94    /// Shared access to the typed register block.
95    #[inline]
96    pub fn regs(&self) -> &TimBasicRegs {
97        // SAFETY: see [`crate::hwcore::regs::dsi::Dsi::regs`].
98        unsafe { &*self.base.as_ptr() }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    #[test]
107    fn tim6_sr_matches_legacy_constant() {
108        assert_eq!(TIM6_BASE + offset_of!(TimBasicRegs, sr), 0x4000_1010);
109    }
110
111    #[test]
112    fn tim7_layout_matches_freertos_entry_constants() {
113        assert_eq!(TIM7_BASE + offset_of!(TimBasicRegs, cr1), 0x4000_1400);
114        assert_eq!(TIM7_BASE + offset_of!(TimBasicRegs, dier), 0x4000_140C);
115        assert_eq!(TIM7_BASE + offset_of!(TimBasicRegs, sr), 0x4000_1410);
116        assert_eq!(TIM7_BASE + offset_of!(TimBasicRegs, egr), 0x4000_1414);
117        assert_eq!(TIM7_BASE + offset_of!(TimBasicRegs, cnt), 0x4000_1424);
118        assert_eq!(TIM7_BASE + offset_of!(TimBasicRegs, psc), 0x4000_1428);
119        assert_eq!(TIM7_BASE + offset_of!(TimBasicRegs, arr), 0x4000_142C);
120    }
121}