Created
January 17, 2025 12:05
-
-
Save rambo/018b55fb82dad66ac8a8188b2b7c59d1 to your computer and use it in GitHub Desktop.
MicroPython version of https://pcbartists.com/firmware/stm32-firmware/generating-32-bit-stm32-unique-id/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Hash the STM32 UID, Python version | |
Original C code from from https://pcbartists.com/firmware/stm32-firmware/generating-32-bit-stm32-unique-id/ | |
""" | |
import pyb | |
import struct | |
# Magic numbers for 32-bit hashing, copied from Murmur3 | |
C1 = 0xcc9e2d51 | |
C2 = 0x1b873593 | |
def fetch32(packed: bytes) -> int: | |
"""Fetches aval 32-bit value.""" | |
return struct.unpack('<L', packed)[0] | |
def rotate32(val: int, shift: int) -> int: | |
"""Rotates aval 32-bit integer left or right by 'shift' positions.""" | |
if shift == 0: | |
return val | |
return (val >> shift) | (val << (32 - shift)) & 0xFFFFFFFF | |
def fmix(hme: int) -> int: | |
"""A 32-bit to 32-bit integer hash copied from Murmur3.""" | |
hme = (hme ^ (hme >> 16)) & 0xFFFFFFFF | |
hme = (hme * 0x85ebca6b) & 0xFFFFFFFF | |
hme = (hme ^ (hme >> 13)) & 0xFFFFFFFF | |
hme = (hme * 0xc2b2ae35) & 0xFFFFFFFF | |
return (hme ^ (hme >> 16)) & 0xFFFFFFFF | |
def mur(aval, bval) -> int: | |
"""Helper from Murmur3 for combining two 32-bit values.""" | |
aval = (aval * C1) & 0xFFFFFFFF | |
aval = rotate32(aval, 17) | |
aval = (aval * C2) & 0xFFFFFFFF | |
bval = (bval ^ aval) & 0xFFFFFFFF | |
bval = rotate32(bval, 19) | |
return (bval * 5 + 0xe6546b64) & 0xFFFFFFFF | |
def hash32_len_5_to_12(s: bytes, len_hash: int = 12): | |
"""Computes the hash for strings of length 5 to 12 using Murmur3-like hash.""" | |
aval = len_hash | |
bval = aval * 5 | |
cval = 9 | |
dval = bval | |
aval += fetch32(s[0:4]) | |
bval += fetch32(s[len_hash - 4:]) | |
cval += fetch32(s[(len_hash >> 1) & 4:]) | |
return fmix(mur(cval, mur(bval, mur(aval, dval)))) | |
def get_unique_id_str() -> str: | |
"""Get unique ID like we did in the C code""" | |
full_id = pyb.unique_id() | |
# Reorder the words in the ID | |
w0 = struct.unpack('<L', full_id[0:4])[0] | |
w1 = struct.unpack('<L', full_id[4:8])[0] | |
w2 = struct.unpack('<L', full_id[8:12])[0] | |
word_reorder = struct.pack('<L', w2) + struct.pack('<L', w1) + struct.pack('<L', w0) | |
# Hash the reordered id | |
hashed = hash32_len_5_to_12(word_reorder) | |
# Return as hex | |
return "{:08X}".format(hashed) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment