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}