Teensy 4.0 Serial Number

wangnick

Well-known member
Dear all,

on the Teensy 3.x there is a 32-bit unique id in one of the records of the program-once area of the flash. You can retrieve it using e.g. https://github.com/sstaub/TeensyID.

Stefan also constructs a MAC address using 04:E9:E5 and then the three lower bytes of said serial number.

On the Teensy 4.0 I found a 64-bit unique id in the OCOTP configuration and manufacturing info area (CFG0/CFG1), probably programmed by NXP. I also found a six byte MAC address there under MAC1/MAC0 as 04:E9:E5:xx:yy:zz, so probably programmed by Paul.

Two question:

1. For the Teensy 3.x is it the well accepted way to compose the MAC address as described above from Pauls serial number?
2. For the Teensy 4.0 can we rely on the three lower bytes of the MAC address to constitute a unique serial number? And if yes, is it unique only for Teensy 4.0, or for all Teensy's?

Kind regards,
Sebastian

Code:
static const uint32_t BAUD = 3000000;
static const char SWID_PGM[] PROGMEM = __FILE__ ", " __DATE__ " " __TIME__;
#define Sln(var) Serial.print(#var); Serial.print(": "); Serial.println(var);
#define H2ln(var) Serial.print(#var); Serial.print(": "); Serial.printf("%02X\n",var);
#define H8ln(var) Serial.print(#var); Serial.print(": "); Serial.printf("%08X\n",var);

#define OCOTP_CFG0 (*(uint32_t *)0x401F4410)
#define OCOTP_CFG1 (*(uint32_t *)0x401F4420)
#define OCOTP_CFG0A ((uint8_t *)0x401F4410)
#define OCOTP_CFG1A ((uint8_t *)0x401F4420)
#define OCOTP_MAC0 (*(uint32_t *)0x401F4620)
#define OCOTP_MAC1 (*(uint32_t *)0x401F4630)
#define OCOTP_MAC2 (*(uint32_t *)0x401F4640)
#define OCOTP_MAC0A ((uint8_t *)0x401F4620)
#define OCOTP_MAC1A ((uint8_t *)0x401F4630)
#define OCOTP_MAC2A ((uint8_t *)0x401F4640)

void setup() {
  Serial.begin(BAUD);
  Sln(SWID_PGM);
  H8ln(OCOTP_CFG0);
  H8ln(OCOTP_CFG1);
  H2ln(OCOTP_CFG0A[0]);
  H2ln(OCOTP_CFG0A[1]);
  H2ln(OCOTP_CFG0A[2]);
  H2ln(OCOTP_CFG0A[3]);
  H2ln(OCOTP_CFG1A[0]);
  H2ln(OCOTP_CFG1A[1]);
  H2ln(OCOTP_CFG1A[2]);
  H2ln(OCOTP_CFG1A[3]);
  H8ln(OCOTP_MAC0);
  H8ln(OCOTP_MAC1);
  H2ln(OCOTP_MAC0A[0]);
  H2ln(OCOTP_MAC0A[1]);
  H2ln(OCOTP_MAC0A[2]);
  H2ln(OCOTP_MAC0A[3]);
  H2ln(OCOTP_MAC1A[0]);
  H2ln(OCOTP_MAC1A[1]);
  H2ln(OCOTP_MAC1A[2]);
  H2ln(OCOTP_MAC1A[3]);
  H2ln(OCOTP_MAC2A[0]);
  H2ln(OCOTP_MAC2A[1]);
  H2ln(OCOTP_MAC2A[2]);
  H2ln(OCOTP_MAC2A[3]);
}

void loop() {
}

Code:
SWID_PGM: C:\Users\Hobbyraum\Documents\Arduino\teensy4\idtest\idtest.ino, Mar 15 2020 15:55:37
OCOTP_CFG0: 677F011D
OCOTP_CFG1: 303F79D2
OCOTP_CFG0A[0]: 1D
OCOTP_CFG0A[1]: 01
OCOTP_CFG0A[2]: 7F
OCOTP_CFG0A[3]: 67
OCOTP_CFG1A[0]: D2
OCOTP_CFG1A[1]: 79
OCOTP_CFG1A[2]: 3F
OCOTP_CFG1A[3]: 30
OCOTP_MAC0: E50A60BB
OCOTP_MAC1: 000004E9
OCOTP_MAC0A[0]: BB
OCOTP_MAC0A[1]: 60
OCOTP_MAC0A[2]: 0A
OCOTP_MAC0A[3]: E5
OCOTP_MAC1A[0]: E9
OCOTP_MAC1A[1]: 04
OCOTP_MAC1A[2]: 00
OCOTP_MAC1A[3]: 00
OCOTP_MAC2A[0]: 00
OCOTP_MAC2A[1]: 00
OCOTP_MAC2A[2]: 00
OCOTP_MAC2A[3]: 00
 
The user Manitou tested this, so you can be sure it's ok.

For Teensy 4 I use
Code:
static void teensyMAC(uint8_t *mac)
{
  uint32_t m1 = HW_OCOTP_MAC1;
  uint32_t m2 = HW_OCOTP_MAC0;
  mac[0] = m1 >> 8;
  mac[1] = m1 >> 0;
  mac[2] = m2 >> 24;
  mac[3] = m2 >> 16;
  mac[4] = m2 >> 8;
  mac[5] = m2 >> 0;
}
It is unique to all Teensys.
 
Last edited:
Ok, thanks.

Nice to know that HW_OCOTP_MACn are already predefined. Your teensyMAC() confirmes my assumptions.

FWIW, Teensy 3.2 seem to be nmbered 1xxxx, Teensy 3.5/3.6 3xxxx, and Teensy 4.0 Axxxx.

Kind regards,
Sebastian
 
Back
Top