sam4l/serial_num.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Provides a struct that enables access to the unique 120 bit serial number stored in read-only
6//! flash on the sam4l.
7
8use kernel::utilities::StaticRef;
9
10// The sam4l stores a unique 120 bit serial number readable from address 0x0080020C to 0x0080021A
11// This value cannot be written to normally, and instead requires special instructions to overwrite,
12// which we do not implement. Because this number is stored in the user page of flash memory,
13// it is not cleared by chip erase.
14#[repr(C)]
15struct sam4lSerialRegister {
16 serial_num: [u8; 15],
17}
18
19const SERIAL_NUM_ADDRESS: StaticRef<sam4lSerialRegister> =
20 unsafe { StaticRef::new(0x0080020C as *const sam4lSerialRegister) };
21
22/// Struct that can be used to get the unique serial number of the sam4l
23pub struct SerialNum {
24 regs: StaticRef<sam4lSerialRegister>,
25}
26
27impl SerialNum {
28 /// Returns a struct that can read the serial number of the sam4l
29 /// This function aliases the memory location of the underlying serial num address, but because
30 /// this struct only provides read operations of the serial number, this is okay.
31 pub fn new() -> SerialNum {
32 SerialNum {
33 regs: SERIAL_NUM_ADDRESS,
34 }
35 }
36
37 /// Returns the 120-bit serial number of the sam4l in a byte array
38 pub fn get(&self) -> [u8; 15] {
39 self.regs.serial_num
40 }
41
42 /// Helper function for simply returning the lower 64 bits of the serial number
43 /// as a u64 rather than a byte array
44 pub fn get_lower_64(&self) -> u64 {
45 let full_num = self.regs.serial_num;
46 full_num
47 .iter()
48 .rev()
49 .take(8)
50 .enumerate()
51 .fold(0u64, |sum, (i, &val)| sum + ((val as u64) << (i * 8)))
52 }
53}