stm32_device_signature/
lib.rs

1//! This crate provides a way to access Device electronic signature
2//! items on STM32 microcontrollers.
3//!
4//! You need to pass one of the features in order to use this crate:
5//! * `stm32f0`
6//! * `stm32f1`
7//! * `stm32f2`
8//! * `stm32f3`
9//! * `stm32f4`
10//! * `stm32f72x`
11//! * `stm32f73x`
12//! * `stm32f76x`
13//! * `stm32f77x`
14//! * `stm32g0`
15//! * `stm32h72x`
16//! * `stm32h73x`
17//! * `stm32h74x`
18//! * `stm32h75x`
19//! * `stm32h7ax`
20//! * `stm32h7bx`
21//! * `stm32l0`
22//! * `stm32l4`
23//! * `stm32wb5x`
24
25#![no_std]
26
27use cortex_m::interrupt;
28
29#[cfg(any(feature = "stm32f0", feature = "stm32f3"))]
30mod pointers {
31    pub const DEVICE_ID_PTR: *const u8 = 0x1FFF_F7AC as _;
32    pub const FLASH_SIZE_PTR: *const u16 = 0x1FFF_F7CC as _;
33}
34
35#[cfg(feature = "stm32f1")]
36mod pointers {
37    pub const DEVICE_ID_PTR: *const u8 = 0x1FFF_F7E8 as _;
38    pub const FLASH_SIZE_PTR: *const u16 = 0x1FFF_F7E0 as _;
39}
40
41#[cfg(any(feature = "stm32f2", feature = "stm32f4"))]
42mod pointers {
43    pub const DEVICE_ID_PTR: *const u8 = 0x1FFF_7A10 as _;
44    pub const FLASH_SIZE_PTR: *const u16 = 0x1FFF_7A22 as _;
45}
46
47#[cfg(any(feature = "stm32f72x", feature = "stm32f73x"))]
48mod pointers {
49    pub const DEVICE_ID_PTR: *const u8 = 0x1FF0_7A10 as _;
50    pub const FLASH_SIZE_PTR: *const u16 = 0x1FF0_7A22 as _;
51}
52
53#[cfg(any(feature = "stm32f76x", feature = "stm32f77x"))]
54mod pointers {
55    pub const DEVICE_ID_PTR: *const u8 = 0x1FF0_F420 as _;
56    pub const FLASH_SIZE_PTR: *const u16 = 0x1FF0_F442 as _;
57}
58
59#[cfg(any(feature = "stm32g0", feature = "stm32l4", feature = "stm32wb5x"))]
60mod pointers {
61    pub const DEVICE_ID_PTR: *const u8 = 0x1FFF_7590 as _;
62    pub const FLASH_SIZE_PTR: *const u16 = 0x1FFF_75E0 as _;
63}
64
65#[cfg(any(
66    feature = "stm32h72x",
67    feature = "stm32h73x",
68    feature = "stm32h74x",
69    feature = "stm32h75x"
70))]
71mod pointers {
72    pub const DEVICE_ID_PTR: *const u8 = 0x1FF1_E800 as _;
73    pub const FLASH_SIZE_PTR: *const u16 = 0x1FF1_E880 as _;
74}
75
76#[cfg(any(feature = "stm32h7ax", feature = "stm32h7bx"))]
77mod pointers {
78    pub const DEVICE_ID_PTR: *const u8 = 0x08FF_F800 as _;
79    pub const FLASH_SIZE_PTR: *const u16 = 0x08FF_F80C as _;
80}
81
82#[cfg(feature = "stm32l0")]
83mod pointers {
84    pub const DEVICE_ID_PTR: *const u8 = 0x1FF8_0050 as _;
85    pub const FLASH_SIZE_PTR: *const u16 = 0x1FF8_007C as _;
86}
87
88use pointers::*;
89
90
91/// Returns a 12-byte unique device ID
92pub fn device_id() -> &'static [u8; 12] {
93    unsafe { &*DEVICE_ID_PTR.cast::<[u8; 12]>() }
94}
95
96
97/// Returns a string with a hex-encoded unique device ID
98pub fn device_id_hex() -> &'static str {
99    static mut DEVICE_ID_STR: [u8; 24] = [0; 24];
100
101    unsafe {
102        if DEVICE_ID_STR.as_ptr().read_volatile() == 0 {
103            interrupt::free(|_| {
104                let hex = b"0123456789abcdef";
105                for (i, b) in device_id().iter().enumerate() {
106                    let lo = b & 0xf;
107                    let hi = (b >> 4) & 0xfu8;
108                    DEVICE_ID_STR[i*2] = hex[hi as usize];
109                    DEVICE_ID_STR[i*2+1] = hex[lo as usize];
110                }
111            });
112        }
113
114        core::str::from_utf8_unchecked(&DEVICE_ID_STR)
115    }
116}
117
118
119/// Returns the Flash memory size of the device in Kbytes
120pub fn flash_size_kb() -> u16 {
121    unsafe { *FLASH_SIZE_PTR }
122}