Skip to content

Commit 421b01a

Browse files
committed
Add signature support
1 parent 5e5b81f commit 421b01a

File tree

5 files changed

+158
-0
lines changed

5 files changed

+158
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2121
- `RccBus`, `Enable`, `Reset` traits and implementations for peripherals ([#299])
2222
- Support cortex-m-rt `v0.7.0` but still allow `v0.6.13` ([#283])
2323
- Make timer `InterruptTypes` fields public to be useful. ([#304])
24+
- Add support for the internal **signature** peripheral ([#281])
2425

2526
### Fixed
2627

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ pub mod rcc;
188188
#[cfg_attr(docsrs, doc(cfg(feature = "rtc")))]
189189
pub mod rtc;
190190
pub mod serial;
191+
pub mod signature;
191192
pub mod spi;
192193
pub mod syscfg;
193194
pub mod timer;

src/signature.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
//! Device electronic signature
2+
//!
3+
//! (stored in flash memory)
4+
use core::fmt;
5+
use core::str;
6+
7+
use core::convert::TryInto;
8+
9+
macro_rules! define_ptr_type {
10+
($name: ident, $ptr: expr) => {
11+
impl $name {
12+
fn ptr() -> *const Self {
13+
$ptr as *const _
14+
}
15+
16+
/// Returns a wrapped reference to the value in flash memory
17+
pub fn get() -> &'static Self {
18+
unsafe { &*Self::ptr() }
19+
}
20+
}
21+
};
22+
}
23+
24+
/// Uniqure Device ID register
25+
#[repr(C, packed)]
26+
pub struct Uid {
27+
x: u16,
28+
y: u16,
29+
waf: u8,
30+
lot: [u8; 7],
31+
}
32+
define_ptr_type!(Uid, 0x1FFF_F7AC);
33+
34+
#[cfg(feature = "defmt")]
35+
impl defmt::Format for Uid {
36+
fn format(&self, f: defmt::Formatter) {
37+
defmt::write!(
38+
f,
39+
"Peripheral {{ x: {:x}, y: {:x}, waf: {}, lum: {}}}",
40+
{ self.x },
41+
{ self.y },
42+
{ self.waf },
43+
{ self.lot_number() },
44+
);
45+
}
46+
}
47+
48+
impl fmt::Debug for Uid {
49+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50+
f.debug_struct("Uid")
51+
.field("x", &self.x())
52+
.field("y", &self.y())
53+
.field("waf", &self.waf)
54+
.field("lot", &self.lot_number())
55+
.finish()
56+
}
57+
}
58+
59+
fn bcd_to_num(bcd_num: u16) -> u16 {
60+
bcd_num
61+
.to_ne_bytes()
62+
.iter()
63+
.enumerate()
64+
.map(|(i, byte)| (i * 2, (*byte & 0xF0) >> 4, *byte & 0x0F))
65+
.map(|(i, high_nibble, low_nibble)| {
66+
let i: u32 = i.try_into().unwrap_or_default(); // This should never overflow
67+
u16::from(high_nibble) * 10u16.pow(i + 1) + u16::from(low_nibble) * 10u16.pow(i)
68+
})
69+
.sum()
70+
}
71+
72+
impl Uid {
73+
/// X coordinate on wafer in BCD format
74+
pub fn x_bcd(&self) -> u16 {
75+
self.x
76+
}
77+
78+
/// X coordinate on wafer
79+
pub fn x(&self) -> u16 {
80+
bcd_to_num(self.x)
81+
}
82+
83+
/// Y coordinate on wafer in BCD format
84+
pub fn y_bcd(&self) -> u16 {
85+
self.y
86+
}
87+
88+
/// Y coordinate on wafer
89+
pub fn y(&self) -> u16 {
90+
bcd_to_num(self.y)
91+
}
92+
93+
/// Wafer number
94+
pub fn wafer_number(&self) -> u8 {
95+
self.waf
96+
}
97+
98+
/// Lot number
99+
pub fn lot_number(&self) -> &str {
100+
// Lets ignore the last byte, because it is a '\0' character.
101+
unsafe { str::from_utf8_unchecked(&self.lot[..6]) }
102+
}
103+
}
104+
105+
/// Size of integrated flash
106+
#[derive(Debug)]
107+
#[repr(C)]
108+
pub struct FlashSize(u16);
109+
define_ptr_type!(FlashSize, 0x1FFF_F7CC);
110+
111+
impl FlashSize {
112+
/// Read flash size in kilobytes
113+
pub fn kilo_bytes(&self) -> u16 {
114+
self.0
115+
}
116+
117+
/// Read flash size in bytes
118+
pub fn bytes(&self) -> usize {
119+
usize::from(self.kilo_bytes()) * 1024
120+
}
121+
}

testsuite/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ harness = false
4747
name = "watchdog"
4848
harness = false
4949

50+
[[test]]
51+
name = "signature"
52+
harness = false
53+
5054
[dependencies]
5155
cfg-if = "1.0"
5256
cortex-m = "0.7.0"

testsuite/tests/signature.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use testsuite as _;
5+
6+
use stm32f3xx_hal as hal;
7+
8+
use hal::signature::{FlashSize, Uid};
9+
10+
#[defmt_test::tests]
11+
mod tests {
12+
use super::*;
13+
use defmt::{self, assert_eq};
14+
15+
#[test]
16+
fn test_uid() {
17+
let uid = Uid::get();
18+
defmt::debug!("{}", uid);
19+
defmt::debug!("{}", defmt::Debug2Format(&uid));
20+
defmt::debug!("{}", uid.x());
21+
defmt::debug!("{}", uid.y());
22+
}
23+
24+
#[test]
25+
fn test_flash_size() {
26+
let flash = FlashSize::get();
27+
defmt::debug!("Flash Size: {} kB", flash.kilo_bytes());
28+
29+
assert_eq!(flash.bytes(), usize::from(flash.kilo_bytes()) * 1024);
30+
}
31+
}

0 commit comments

Comments
 (0)