Skip to content

Commit

Permalink
read STM32 unique device identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
surban committed Apr 8, 2023
1 parent 00ab742 commit f30c364
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to OpenEMC will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.6.2 - 2023-04-08
### Added
- read unique device identifier

## 0.6.1 - 2023-03-07
### Fixed
- system not powering on after watchdog reset
Expand Down
43 changes: 43 additions & 0 deletions openemc-driver/openemc.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,28 @@ int openemc_read_u64(struct openemc *emc, u8 command, u64 *value)
}
EXPORT_SYMBOL_GPL(openemc_read_u64);

int openemc_read_u128(struct openemc *emc, u8 command, u64 *value_lo,
u64 *value_hi)
{
u8 buf[16];
int ret;

ret = openemc_request(emc, REQ_READ, command, ARRAY_SIZE(buf), buf);
if (ret < 0)
return ret;

*value_lo = (u64)buf[0] | (u64)buf[1] << 8 | (u64)buf[2] << 16 |
(u64)buf[3] << 24 | (u64)buf[4] << 32 | (u64)buf[5] << 40 |
(u64)buf[6] << 48 | (u64)buf[7] << 56;
*value_hi = (u64)buf[8] | (u64)buf[9] << 8 | (u64)buf[10] << 16 |
(u64)buf[11] << 24 | (u64)buf[12] << 32 |
(u64)buf[13] << 40 | (u64)buf[14] << 48 |
(u64)buf[15] << 56;

return 0;
}
EXPORT_SYMBOL_GPL(openemc_read_u128);

int openemc_write_u64(struct openemc *emc, u8 command, u64 value)
{
u8 buf[8];
Expand Down Expand Up @@ -1290,6 +1312,15 @@ static ssize_t openemc_board_model_show(struct device *dev,
}
static DEVICE_ATTR_RO(openemc_board_model);

static ssize_t openemc_unique_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct openemc *emc = dev_get_drvdata(dev);
return sprintf(buf, "%08llx%016llx", emc->unique_id[1],
emc->unique_id[0]);
}
static DEVICE_ATTR_RO(openemc_unique_id);

static ssize_t openemc_boot_reason_show(struct device *dev,
struct device_attribute *attr,
char *buf)
Expand Down Expand Up @@ -1466,6 +1497,7 @@ static struct attribute *openemc_attrs[] = {
&dev_attr_openemc_flashable.attr,
&dev_attr_openemc_emc_model.attr,
&dev_attr_openemc_board_model.attr,
&dev_attr_openemc_unique_id.attr,
&dev_attr_openemc_boot_reason.attr,
&dev_attr_openemc_reset_status.attr,
&dev_attr_openemc_start_reason.attr,
Expand Down Expand Up @@ -1565,6 +1597,11 @@ static int openemc_get_info(struct openemc *emc)
if (ret < 0)
return ret;

ret = openemc_read_u128(emc, OPENEMC_UNIQUE_ID, &emc->unique_id[0],
&emc->unique_id[1]);
if (ret < 0)
return ret;

ret = openemc_read_u16(emc, OPENEMC_BOOT_REASON, &emc->boot_reason);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -1696,7 +1733,11 @@ static int openemc_i2c_probe(struct i2c_client *i2c)
return 0;
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
static void openemc_i2c_remove(struct i2c_client *i2c)
#else
static int openemc_i2c_remove(struct i2c_client *i2c)
#endif
{
struct openemc *emc = i2c_get_clientdata(i2c);

Expand All @@ -1705,7 +1746,9 @@ static int openemc_i2c_remove(struct i2c_client *i2c)
irq_domain_remove(emc->irq_domain);
}

#if !(LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
return 0;
#endif
}

static struct i2c_driver openemc_i2c_driver = {
Expand Down
4 changes: 4 additions & 0 deletions openemc-driver/openemc.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define OPENEMC_EMC_MODEL 0x02
#define OPENEMC_BOARD_MODEL 0x03
#define OPENEMC_BOOTLOADER_VERSION 0x04
#define OPENEMC_UNIQUE_ID 0x05
#define OPENEMC_COPYRIGHT 0x06
#define OPENEMC_MFD_CELL 0x07
#define OPENEMC_BOOT_REASON 0x08
Expand Down Expand Up @@ -224,6 +225,7 @@ struct openemc {
char copyright[8 * OPENEMC_MAX_DATA_SIZE];
u8 emc_model;
char board_model[OPENEMC_MAX_DATA_SIZE + 1];
u64 unique_id[2];
u16 boot_reason;
u8 reset_status;
u8 start_reason;
Expand Down Expand Up @@ -261,6 +263,8 @@ int openemc_read_u32(struct openemc *emc, u8 command, u32 *value);
int openemc_write_u32(struct openemc *emc, u8 command, u32 value);
int openemc_read_u64(struct openemc *emc, u8 command, u64 *value);
int openemc_write_u64(struct openemc *emc, u8 command, u64 value);
int openemc_read_u128(struct openemc *emc, u8 command, u64 *value_lo,
u64 *value_hi);
int openemc_read_data(struct openemc *emc, u8 command, u8 len, u8 *data);
int openemc_write_data(struct openemc *emc, u8 command, u8 len, const u8 *data);

Expand Down
2 changes: 1 addition & 1 deletion openemc-firmware/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion openemc-firmware/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "openemc-firmware"
description = "OpenEMC Firmware"
authors = ["Sebastian Urban <[email protected]>"]
license = "GPL-3.0"
version = "0.6.1"
version = "0.6.2"
publish = false
edition = "2021"

Expand Down
22 changes: 22 additions & 0 deletions openemc-firmware/src/i2c_reg_slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,4 +326,26 @@ impl<const BUFFER: usize> Response<BUFFER> {
((value >> 56) & 0xff) as u8,
])
}

/// Sets the register value to an u128 with LSB first.
pub fn set_u128(value: u128) -> Self {
Self::set(&[
(value & 0xff) as u8,
((value >> 8) & 0xff) as u8,
((value >> 16) & 0xff) as u8,
((value >> 24) & 0xff) as u8,
((value >> 32) & 0xff) as u8,
((value >> 40) & 0xff) as u8,
((value >> 48) & 0xff) as u8,
((value >> 56) & 0xff) as u8,
((value >> 64) & 0xff) as u8,
((value >> 72) & 0xff) as u8,
((value >> 80) & 0xff) as u8,
((value >> 88) & 0xff) as u8,
((value >> 96) & 0xff) as u8,
((value >> 104) & 0xff) as u8,
((value >> 112) & 0xff) as u8,
((value >> 120) & 0xff) as u8,
])
}
}
5 changes: 4 additions & 1 deletion openemc-firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ use crate::{
pwm::PwmTimer,
rtc::{ClockSrc, Rtc},
supply::{max14636::Max14636, stusb4500::StUsb4500, PowerSupply},
util::{array_from_u16, array_from_u64, array_to_u16, array_to_u64},
util::{array_from_u16, array_from_u64, array_to_u16, array_to_u64, unique_device_id},
watchman::Watchman,
};
use openemc_shared::{BootInfo, BootReason};
Expand Down Expand Up @@ -338,6 +338,7 @@ mod app {
}
defmt::info!("EMC model: 0x{:02x}", bi.emc_model);
defmt::info!("board model: {:a}", bi.board_model());
defmt::info!("unique id: {:024x}", unique_device_id());
defmt::info!("I2C address: 0x{:02x} (pins remapped: {:?})", ThisBoard::I2C_ADDR, ThisBoard::I2C_REMAP);
defmt::info!("IRQ pin: {} (mode: 0b{:04b})", ThisBoard::IRQ_PIN, ThisBoard::IRQ_PIN_CFG);
BootReason::log(bi.boot_reason);
Expand Down Expand Up @@ -1110,6 +1111,7 @@ mod app {
let respond_u16 = |response: u16| respond(Response::set_u16(response));
let respond_u32 = |response: u32| respond(Response::set_u32(response));
let respond_u64 = |response: u64| respond(Response::set_u64(response));
let respond_u128 = |response: u128| respond(Response::set_u128(response));

match evt {
Event::Read { reg: reg::ID } => {
Expand All @@ -1122,6 +1124,7 @@ mod app {
Some(v) => respond_slice(v),
None => respond_slice(&[0]),
},
Event::Read { reg: reg::UNIQUE_ID } => respond_u128(unique_device_id()),
Event::Read { reg: reg::COPYRIGHT } => {
respond_clipped(COPYRIGHT.get(*cx.local.copyright_offset..).unwrap_or_default())
}
Expand Down
3 changes: 3 additions & 0 deletions openemc-firmware/src/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pub const BOARD_MODEL: u8 = 0x03;
/// Read bootloader version (string).
pub const BOOTLOADER_VERSION: u8 = 0x04;

/// Read 96-bit unique device identifier (u128).
pub const UNIQUE_ID: u8 = 0x05;

/// Copyright.
/// Read: string starting at offset.
/// Write u8: set offset.
Expand Down
14 changes: 13 additions & 1 deletion openemc-firmware/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Debug functions.

use core::mem::size_of;
use core::{mem::size_of, ptr};
use defmt::unwrap;

// use crate::CPU_CLOCK;
Expand Down Expand Up @@ -66,3 +66,15 @@ pub fn array_to_u16<const D: usize>(flat: &[u8]) -> [u16; D] {
}
data
}

/// 96-bit unique device identifier.
pub fn unique_device_id() -> u128 {
const BASE: usize = 0x1FFFF7E8;
unsafe {
let a = ptr::read_unaligned(BASE as *const u16) as u128;
let b = ptr::read_unaligned((BASE + 2) as *const u16) as u128;
let c = ptr::read_unaligned((BASE + 4) as *const u32) as u128;
let d = ptr::read_unaligned((BASE + 8) as *const u32) as u128;
a | (b << 16) | (c << 32) | (d << 64)
}
}

0 comments on commit f30c364

Please sign in to comment.