stm32l4xx_hal/
signature.rs

1//! Device electronic signature
2//!
3//! (stored in flash memory)
4//!
5//! Based on the STM32F4xx HAL.
6
7use core::str::from_utf8_unchecked;
8
9/// This is the test voltage, in millivolts of the calibration done at the factory
10pub const VDDA_CALIB_MV: u32 = 3000;
11
12macro_rules! define_ptr_type {
13    ($name: ident, $ptr: expr) => {
14        impl $name {
15            fn ptr() -> *const Self {
16                $ptr as *const _
17            }
18
19            /// Returns a wrapped reference to the value in flash memory
20            pub fn get() -> &'static Self {
21                unsafe { &*Self::ptr() }
22            }
23        }
24    };
25}
26
27/// Uniqure Device ID register
28#[derive(Hash, Debug)]
29#[repr(C)]
30pub struct Uid {
31    x: u16,
32    y: u16,
33    waf_lot: [u8; 8],
34}
35define_ptr_type!(Uid, 0x1FFF_7590);
36
37impl Uid {
38    /// X coordinate on wafer
39    pub fn x(&self) -> u16 {
40        self.x
41    }
42
43    /// Y coordinate on wafer
44    pub fn y(&self) -> u16 {
45        self.y
46    }
47
48    /// Wafer number
49    pub fn waf_num(&self) -> u8 {
50        self.waf_lot[0]
51    }
52
53    /// Lot number
54    pub fn lot_num(&self) -> &str {
55        unsafe { from_utf8_unchecked(&self.waf_lot[1..]) }
56    }
57
58    /// As a byte array
59    pub fn as_bytes() -> &'static [u8; 12] {
60        unsafe { &*(Self::ptr() as *const _) }
61    }
62}
63
64/// Size of integrated flash
65#[derive(Debug)]
66#[repr(C)]
67pub struct FlashSize(u16);
68define_ptr_type!(FlashSize, 0x1FFF_75E0);
69
70impl FlashSize {
71    /// Read flash size in kilobytes
72    pub fn kilo_bytes(&self) -> u16 {
73        self.0
74    }
75
76    /// Read flash size in bytes
77    pub fn bytes(&self) -> usize {
78        usize::from(self.kilo_bytes()) * 1024
79    }
80}
81
82/// ADC VREF calibration value is stored in at the factory
83#[derive(Debug)]
84#[repr(C)]
85pub struct VrefCal(u16);
86define_ptr_type!(VrefCal, 0x1FFF_75AA);
87
88impl VrefCal {
89    /// Read calibration value
90    pub fn read(&self) -> u16 {
91        self.0
92    }
93}
94
95/// A temperature reading taken at 30°C stored at the factory
96/// aka TS_CAL1 in reference manual
97#[derive(Debug)]
98#[repr(C)]
99pub struct VtempCalLow(u16);
100define_ptr_type!(VtempCalLow, 0x1FFF_75A8);
101
102impl VtempCalLow {
103    /// aka TS_CAL1_TEMP in reference manual
104    pub const TEMP_DEGREES: u16 = 30;
105    /// Read calibration value
106    pub fn read(&self) -> u16 {
107        self.0
108    }
109}
110
111/// A temperature reading taken at 130°C stored at the factory
112/// aka TS_CAL2 in reference manual
113#[derive(Debug)]
114#[repr(C)]
115pub struct VtempCalHigh(u16);
116define_ptr_type!(VtempCalHigh, 0x1FFF_75CA);
117
118impl VtempCalHigh {
119    /// aka TS_CAL2_TEMP in reference manual
120    /// Feature gate Required: this is 110 for L47x/L48x, 130 for other L4s according to
121    /// https://github.com/STMicroelectronics/STM32CubeL4/blob/5e1553e07706491bd11f4edd304e093b6e4b83a4/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_adc.h#L352-L356
122
123    // L47/L48
124    #[cfg(any(
125        feature = "stm32l471",
126        feature = "stm32l475",
127        feature = "stm32l476",
128        feature = "stm32l486"
129    ))]
130    pub const TEMP_DEGREES: u16 = 110;
131    // else
132    #[cfg(not(any(
133        feature = "stm32l471",
134        feature = "stm32l475",
135        feature = "stm32l476",
136        feature = "stm32l486"
137    )))]
138    pub const TEMP_DEGREES: u16 = 130;
139    /// Read calibration value
140    pub fn read(&self) -> u16 {
141        self.0
142    }
143}