Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 18 of 18

Thread: Serial & MAC Address - Teensy 4.0

  1. #1

    Serial & MAC Address - Teensy 4.0

    Hello All,

    I was wondering if anyone has found a way to pull the serial or MAC address for the Teensy 4.0

    I started looking over my code for 3.x and scouring Paul's git for some clues, but I am not seasoned enough to pull this off quickly.

    If anyone is willing to collaborate, I would be willing to create a library for this supporting all teens'y >= 3.x. Maybe a pull request from here.

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,685
    Didn't see it come up in beta or since - but the Serial Number of Teensy is derived from the MAC ID in this code in ...\hardware\teensy\avr\cores\teensy4\usb_desc.c:
    Code:
    void usb_init_serialnumber(void)
    {
    	char buf[11];
    	uint32_t i, num;
    
    	num = HW_OCOTP_MAC0 & 0xFFFFFF;
    	// add extra zero to work around OS-X CDC-ACM driver bug
    	if (num < 10000000) num = num * 10;
    	ultoa(num, buf, 10);
    	for (i=0; i<10; i++) {
    		char c = buf[i];
    		if (!c) break;
    		usb_string_serial_number_default.wString[i] = c;
    	}
    	usb_string_serial_number_default.bLength = i * 2 + 2;
    That is similar to prior Teensys but MCU specific.

    The RefMan likely explains that and why there are three MAC's indicated and which is desired:
    Code:
    #define HW_OCOTP_MAC0			(IMXRT_OCOTP_VALUE.offset220)
    #define HW_OCOTP_MAC1			(IMXRT_OCOTP_VALUE.offset230)
    #define HW_OCOTP_MAC2			(IMXRT_OCOTP_VALUE.offset240)

  3. #3
    Thanks a bunch @defragster this has me on the right track.

  4. #4
    It appears that all 3 are parts of the MAC address, they are as follows:

    HW_OCOTP_MAC2 - Padding
    HW_OCOTP_MAC1 - OUI
    HW_OCOTP_MAC0 - UID

    Together they make up the mac address.

    The serial is just a derivative of the UID. Is the algorithm used some sort of standard, or just something Paul came up with, anyone?

  5. #5
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,685
    Quote Originally Posted by thagh05t View Post
    It appears that all 3 are parts of the MAC address, they are as follows:

    HW_OCOTP_MAC2 - Padding
    HW_OCOTP_MAC1 - OUI
    HW_OCOTP_MAC0 - UID

    Together they make up the mac address.

    The serial is just a derivative of the UID. Is the algorithm used some sort of standard, or just something Paul came up with, anyone?
    Nice work on the research.

    As noted AFAIK that is the PJRC standard serial number generation from the unique device MAC : "similar to prior Teensys but MCU specific" in where MAC comes from.

  6. #6
    I have hammered out methods for determining the MAC and in turn USB Serial Number for each MCU >= 3.1.

    The library linked in my original post has a lot of the work already done, so I could quite simply just extend the code, but I do not see any information on a UUID for the Teensy 4. Here is a snippet of how it was done for Teensy 3.x

    Code:
    void teensyUUID(uint8_t *uuid) {
    	uint8_t mac[6];
    	teensyMAC(mac);
    	uuid[0] = SIM_UIDML >> 24;
    	uuid[1] = SIM_UIDML >> 16;
    	uuid[2] = SIM_UIDML >> 8;
    	uuid[3] = SIM_UIDML;
    	uuid[4] = SIM_UIDL >> 24;
    	uuid[5] = SIM_UIDL >> 16;
    	uuid[6] = 0x40; // marked as version v4, but this uuid is not random based !!!
    	uuid[7] = SIM_UIDL >> 8;
    	uuid[8] = 0x80; //variant
    	uuid[9] = SIM_UIDL;
    	uuid[10] = mac[0];
    	uuid[11] = mac[1];
    	uuid[12] = mac[2];
    	uuid[13] = mac[3];
    	uuid[14] = mac[4];
    	uuid[15] = mac[5];
    	}

    It isn't really a big deal to me, I wouldn't be using the UID anyways, but just in case anyone was interested.

    If nobody really cares, or it doesn't exist I could either generate a UUID 4 based on known values as a seed or just omit it from the library I intend to write/extend. That is, if anyone is interested or thinks it would be useful. I like what sstaub did with the original, but I feel like on init, having a struct with the data available as a couple different types may be useful.

    Thoughts?

  7. #7
    Senior Member
    Join Date
    Nov 2015
    Location
    Cold hollow VT
    Posts
    117
    Are you aware of TeensyID.h ? It reads out the MAC, Serial # and UUID as well as a few other identifiers. Don't recall who wrote it, but, it works well. Not sure if it supports Teensy 4.0 yet.

  8. #8
    Quote Originally Posted by grease_lighting View Post
    Are you aware of TeensyID.h ? It reads out the MAC, Serial # and UUID as well as a few other identifiers. Don't recall who wrote it, but, it works well. Not sure if it supports Teensy 4.0 yet.
    Hey @grease_lightning,

    Yea, I am aware of TeensyID... That is the library I have been talking about since my initial post albeit I didn't specifically refer to it by name.

    TeensyID does not support Teensy 4.0 and has not been touched in close to 3 years. I was going to fork it and extend the lib, or rewrite it entirely to suit my needs better if others were in line. If not, I got what I needed out of this thread already.

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,685
    @thagh05t: if this was extended for Teensy 4.0 - it would be good to see it shared.

  10. #10
    I basically just used the code from usb_desc.c to port my project over. Big help btw, I'd seen the code you posted a snippet of before, but just thought it was too easy.

    I've not created a library for it yet, but I'll make some time to do this. In the mean time, if anyone is asking similar questions, just point them at this post and ill be glad to answer any questions.

    I've been busy on python projects more lately, so this project is slow moving, please forgive me. Which segues into my next thought.. why not try and run micropython on teensy4? I know theres been some work on this, but I'd really like to push this along, I love python so would naturally love to work my magic with teensy4 using python. Am I the only person who feels this way, is this something others would like to see, or do you guys think the work outweighs the reward?

  11. #11
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,685
    There was another thread looking for T_3.6 serial # info so I came here to see if there was an updated/extended unified TeensyID to point at.

    I've not gotten into python - after BASIC I moved to "C" and stuck there at work - and left that 21 years back and just happy to use what I know … going back to an interpreter just seems super lame

    There have been Teensy Python ports done before IIRC, not sure if there are usable thread links - I even backed a KS to put it on ESP8266 and it has evolved there to ESP32, but on the new ESP32's delivered with python - I just went onto Arduino with C/cpp.

  12. #12
    All of the serial number generation for each teensy is found in the same file. I'll throw together something easily imported that returns a struct of the different identifying components broken down. By modifying those same files I found that you can generate your own serial and mac address. Amongst other things, but you're really not supposed to.

    C is my second favorite language, but pythons simplicity has made it very easy to spin up otherwise complex programs with much less code. I'll have to check out the ESP32 to see if I like it enough to try and make teensy python. I love the teensy for any little project and will likely stick with it. I cannot wait for the moment teensy 4.x comes out with wifi. If not, I'll keep coupling it with the esp8266.

    I've been working on an environment control system for reptiles that I think will be a hit if I ever finish it. As well as some other iot sort of projects.

  13. #13
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,685
    Keep an eye on this thread - with T4 USB wired and WiFi are getting underway … forum.pjrc.com/threads/57701-USB-Host-Ethernet-Driver

  14. #14
    Junior Member
    Join Date
    Oct 2019
    Posts
    4
    Hello,

    has anyone tried the Teensy 3.x methods for getting the chip UID & MAC address from a Teensy 4.0?
    Maybe they all are just the same / can perhaps the 128bit Teensy 3.x UID section simply be extended with the chip definition below?
    Pieced together from earlier work of contributors defragster, cmason et. al., I am copying some code snippets in below (both tested, working fine on a device using T36), perhaps useful to others, too.
    I'd be really keen to do the same for T40, allowing for inter alia porting a product design from T36 to T40.

    Chip UID
    Does anyone know if these SIM_**** registers are still correct / what the (__MK???????__) is for T40?

    Code:
      // 80bit UID Teensy LC
      #if defined (__MKL26Z64__)
      uint32_t uid[3];
      uid[0] = SIM_UIDMH;
      uid[1] = SIM_UIDML;
      uid[2] = SIM_UIDL;
      char uidString[27];
      sprintf(uidString, "%08X-%08X-%08X", uid[0], uid[1], uid[2]);
      
      // 128bit UID Teensy 3.0, 3.1, 3.2, 3.5, 3.6
      #elif defined (__MK20DX128__) || defined (__MK20DX256__) || defined (__MK64FX512__) || defined (__MK66FX1M0__)
      uint32_t uid[4];
      uid[0] = SIM_UIDH;
      uid[1] = SIM_UIDMH;
      uid[2] = SIM_UIDML;
      uid[3] = SIM_UIDL;
      char uidString[36];
      sprintf(uidString, "%08lX-%08lX-%08lX-%08lX", uid[0], uid[1], uid[2], uid[3]);
    MAC address
    Is this still applicable to T40?

    Code:
      byte macB[6];                          // 
      FTFL_FCCOB0   = 0x41;                  // Selects the READONCE command
      FTFL_FCCOB1   = 0x0E;                  // read the 1st half of MAC read once area
      FTFL_FSTAT    = FTFL_FSTAT_CCIF;       // launch command (could just wait a few ms after / suspend until complete if req'd)
      macB[0]       = FTFL_FCCOB5;           // collect only the top three bytes,
      macB[1]       = FTFL_FCCOB6;           // in the right orientation (big endian).
      macB[2]       = FTFL_FCCOB7;           // Skip FTFL_FCCOB4, always 0
      macB[3]       = FTFL_FCCOB9;           // collect only the top three bytes,
      macB[4]       = FTFL_FCCOBA;           // in the right orientation (big endian).
      macB[5]       = FTFL_FCCOBB;           // Skip FTFL_FCCOB8, always 0
      char macC[17] = {0};                   // 
      sprintf(macC,"%02X:%02X:%02X:%02X:%02X:%02X",macB[0],macB[1],macB[2],macB[3],macB[4],macB[5]);

    Thanks in advance for any of your additional insight.
    Last edited by dataplow; 10-07-2019 at 06:18 PM. Reason: typo

  15. #15
    Junior Member
    Join Date
    Oct 2019
    Posts
    4
    Chip UID SIM_**** registers do not seem to work (not declared), had some hopes.
    Having looked at usb_desc.c for instance, T40 only has (__IMXRT1052__) defined, yet when testing, it's definitely (__IMXRT1062__) using a test as per previous post.

    MAC address FTFL_****** business also does not work on T40, unfortunately.
    However, this does (thanks to defragster):

    Code:
      uint32_t macNUM_0;                                    // num 0
      macNUM_0 = HW_OCOTP_MAC0 & 0xFFFFFF;                  // okay could try
      if (macNUM_0 < 10000000) macNUM_0 = macNUM_0 * 10;    // add extra zero to work around OS-X CDC-ACM driver bug
      String macS0 = String(macNUM_0,HEX);                  // get a hex string from 0
    Getting unique (?) but at least different values for the two T40s I now have.
    Tried with HW_OCOTP_MAC1 and HW_OCOTP_MAC2, too, but getting 311A and 0 respectively (latter indeed is just padding), this is identical across my two T40s.
    To construct the actual 12 byte MAC address from this: HW_OCOTP_MAC0 + HW_OCOTP_MAC1 in order, or perhaps (probably) the other way around?
    In any case:
    HW_OCOTP_MAC0 & 0xFFFFFF could just be used as a 3 byte UID I assume, or even
    HW_OCOTP_MAC0 on its own (4 bytes).

  16. #16
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,554
    Quote Originally Posted by dataplow View Post
    To construct the actual 12 byte MAC address
    A mac address is 48 bits, or 6 bytes, not 12.

    The low 24 bits are meant to be the product serial number and the top 24 bits are a OUI (organizationally unique identifier) assigned by IEEE.

    PJRC's OUI is "04:E9:E5". Here's a list of all the registered organizations, in case you're wondering if PJRC really is properly registered.

    https://code.wireshark.org/review/gi..._plain;f=manuf

    NXP reserved space in the fuses for 2 mac addresses. That's why it's 12 bytes. As usual, they used a confusing naming scheme, and in the earlier manuals for 1050 the info was copied incorrectly with parts missing in some places it appeared. Rather confusing...

  17. #17
    Junior Member
    Join Date
    Oct 2019
    Posts
    4
    Quote Originally Posted by PaulStoffregen View Post
    PJRC's OUI is "04:E9:E5". Here's a list of all the registered organizations, in case you're wondering if PJRC really is properly registered.

    https://code.wireshark.org/review/gi..._plain;f=manuf
    Many thanks. Was wondering indeed, but more about whether I am looking at the right data / bitmask when seeking the full unique set, rather than PJRC's registered status...

    Just for correspondence:

    I am no longer sure if the code snippet I posted is resolving the unique part by HW_OCOTP_MAC0 & 0xFFFFFF properly, at least as far as the intended unique MAC address in concerned.
    Reason being, if I do the same mask business on HW_OCOTP_MAC1, I get 00311A rather than 04E9E5, as per Paul's information on the top 24bit OUI (different bitmask perhaps / should I get 04E9E5 from HW_OCOTP_MAC1 somehow?).
    It still works & gets (a hex string for those) unique 3 bytes, which is good enough for identifying hw for code locking purposes (as opposed to a massive i2c pain I just discovered with T40 which definitely wasn't the case with T36, but, different topic).

  18. #18
    Junior Member
    Join Date
    Oct 2019
    Posts
    4
    Quote Originally Posted by dataplow View Post
    ... good enough for identifying hw for code locking purposes (as opposed to a massive i2c pain I just discovered with T40 which definitely wasn't the case with T36, but, different topic).
    I was about to start a topic on this, noting T36's compliance in contrast of T40's lack of it, but I'd like to most happily withdraw that above.
    It seems the brand new Teensyduino 1.48 released yesterday fully resolved I2C slave failures / SDA down while SCK up / hot swap / power loss / etc causing a T40 I2C Master to lock up, therefore, not launching a topic on that.
    So glad it has been addressed, no master/slave comms should ever allow any slave to suspend master op in an infinite wait / loop (I understand that, shockingly, it has been the case with Arduino's Wire lib for years).
    Hot-swapping / overdriving sensors now for testing, with T40 now unphased, great!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •