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