Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 42

Thread: Serial Number of Teensy 3.1

  1. #1
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58

    Serial Number of Teensy 3.1

    Hi guys

    One question. Is possible get the Serial Number of one teensy 3.1 or chip?

    If it is possible, how can i do it? which command?

    Thanks in advance

  2. #2
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,991
    Each Teensy 3.0 or 3.1 has a MAC number that can be used as a unique id for ethernet addresses. This thread covers how to read it: http://forum.pjrc.com/threads/91-teensy-3-MAC-address.

  3. #3
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    Fantastic.

    Thank you very much indee.

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,171
    I'd recommend disabling interrupts while manipulating the flash controller. That may be overly paranoid, but it's such a short time for something you probably only do once, so the cost is low.

  5. #5
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    Thanks for the advice.

  6. #6
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    With this code will be enough?

    Code:
    void loop()
    {
      noInterrupts();
    
      read_mac();
    
      interrupts();
      
      "PROGRAM CODE"
    
    }

  7. #7
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Note: the "read_mac()" contributed function yields 6 of of the 8 bytes. The 6 are intended for use with the ethernet controllers such as WiZnet (other than the 5500 chip) that do not come with a pre-assigned MAC address.

    The 8 byte unique ID number given by PJRC can be had with Teensy3 code such as this:
    Code:
    static uint8_t myID[8];
    
    void read_EE(uint8_t word, uint8_t *buf, uint8_t offset)  {
    	noInterrupts();
    	FTFL_FCCOB0 = 0x41;             // Selects the READONCE command
    	FTFL_FCCOB1 = word;             // read the given word of read once area
    
    	// launch command and wait until complete
    	FTFL_FSTAT = FTFL_FSTAT_CCIF;
    	while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF))
    		;
    	*(buf+offset+0)	= FTFL_FCCOB4;
    	*(buf+offset+1) = FTFL_FCCOB5;       
    	*(buf+offset+2) = FTFL_FCCOB6;       
    	*(buf+offset+3) = FTFL_FCCOB7;       
    	interrupts();
    }
    
    		
    void read_myID() {
    	read_EE(0xe,myID,0); // should be 04 E9 E5 xx, this being PJRC's registered OUI
    	read_EE(0xf,myID,4); // xx xx xx xx
    
    }
    
    void print_myID()  {
    	Serial.printf(" ID byte = %d decimal, from ", myID[7]);
    	for (int i=0; i < sizeof(myID); i++)
    		Serial.printf("%02X:", myID[i]);
    }
    Last edited by stevech; 04-04-2014 at 04:13 PM.

  8. #8
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    Thanks.

    And this my_id is in some library? or is a standard function?

    Cheers

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,171
    Quote Originally Posted by stevech View Post
    Note: the "read_mac()" contributed function yields 6 of of the 8 bytes.
    The upper byte of the OUI is unused.

    In theory, the serial number is 32 bits. But at the rate we've been assigning the serial numbers, the low 24 bits will not overflow for well over 600 years!

  10. #10
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    FYI: If the serial number is used to derive an Ethernet MAC address, the most significant byte has some IEEE defined coding.
    as shown in the graphic, here
    http://en.wikipedia.org/wiki/MAC_address

    Bit 2, if set to 1, means the MAC address is locally administered; Not registered with the IEEE.
    So if you prefer, you can set this bit and all other bits/bytes are up to you to choose, for your LAN. Just make sure you make each device unique. And don't use that MAC address for an edge router to a public network. With NATing routers, this is never an issue.

    But since Teensy 3's have a unique serial number, you might use that number to derive the 6 byte Ethernet MAC address. The PJRC OUI group is 04 E9 E5 as the 3 MSBs. The lower 3 bytes can be the the lowest 3 of the 8 byte serial number. These 3 bytes (24 bits) are an ascending number used to serialize each Teensy, per Paul.

    An "OUI" is 64 bits. An Ethernet MAC address (48 bits) can be derived from an OUI, and an OUI may have other purposes too.

    Technically, one should have approval by PJRC to use addresses in their block starting with 04 E9 E5 - perhaps a blanket statement by PJRC that it be used only for certain purposes beyond the 64 bit product serial number.

  11. #11
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,171
    Quote Originally Posted by stevech View Post
    Technically, one should have approval by PJRC to use addresses in their block starting with 04 E9 E5 - perhaps a blanket statement by PJRC that it be used only for certain purposes beyond the 64 bit product serial number.
    PJRC paid for "04 E9 E5" to allow every Teensy 3.x project to have a proper mac address for use with ethernet chips like W5100 & W5200. OUIs have other purposes, but PJRC's main intention was mac addresses with ethernet and other network protocols that require mac addresses.

    Our purpose is to facilitate developing hobbyist, academic and even commercial projects. If you're planning to use the PJRC OUI for some other purpose, please discuss it here. If you're buying PJRC-made Teensy boards and using the number from the permanent memory, and if your use isn't something prohibited by IEEE or USA law, odds are good PJRC will approve of your use (whether you really need PJRC's approval is a good question). Obviously I can't make a blanket statement about uses I don't even anticipate, but I can tell you we paid for an official OUI from IEEE specifically for ethernet and networking projects using Teensy3.

    When/if the serial number ever increments past 16777215 (in approx 670+ years at the current rate), PJRC will need to obtain a new OUI to replace "04 E9 E5". I have a lot of plans for future developments on the Teensy platform. This is probably the least urgent of all the possible pending issues!
    Last edited by PaulStoffregen; 04-04-2014 at 10:44 PM.

  12. #12
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    Hi again guys, i only know how get the Id or Mac Adress of teensy for a project.

    Thanks

  13. #13
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,171
    Did you try the code from reply #7 ?

  14. #14
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    Not yet

    I am using teensyduino. And i don't know if write these code in a new library or use it in my sketch.
    Or if there is some existent library that use it.

    thanks
    Last edited by carcaes1; 04-05-2014 at 08:04 AM.

  15. #15
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,171
    The code on #7 appears to be able to simply copy into your sketch in Arduino.

    Then you could just call its print_myID() function, perhaps like this:

    Code:
    void setup() {
    }
    void loop() {
      print_myID();
      delay(1000);
    }
    It's ok to try stuff. That's how you learn things. I'd highly recommend giving this a try.

    If it doesn't work and you need help, please spend a few minutes to compose a good question, with a screenshot or exact copy of any error message, or a precise description of what went wrong. Short questions lacking details are impossible to answer. Detailed questions with specific info are the way to get good help here!

  16. #16
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    Thanks again

    I will test it

    Cheers

  17. #17
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,805
    Need to Read before Print - and it worked for me with Msg #7 code dropped in:

    Code:
    void loop() {
      // put your main code here, to run repeatedly:
      read_myID();
      print_myID();
      delay(1000);
    }
    Modified the Print to show Serial # as reported in USB (with '0' padded on the end):

    Code:
    unsigned long serialNum = 0;
    void print_myID()  {
      int ii;
      Serial.printf(" ID byte = %d decimal, from ", myID[7]);
      for (ii = 0; ii < sizeof(myID); ii++) {
        if ( ii )
          Serial.printf(" :");
        Serial.printf("%02X", myID[ii]);
        if ( ii > 3)
          serialNum = (serialNum << 8) + myID[ii];
      }
      Serial.printf("   Serial# %lu0\n", serialNum);
    }
    Last edited by defragster; 04-17-2015 at 07:08 AM.

  18. #18
    Member
    Join Date
    Mar 2014
    Location
    Valencia
    Posts
    58
    Thanks a lot

    Cheers

  19. #19
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,805
    Is there a unique meaning to what is printed as the "ID byte = " in the code in m# 7 above?
    Serial.printf(" ID byte = %d decimal, from ", myID[7]);

    Is there a way at run time to see what Teensy you are on [LC .vs. 3.1, etc]?
    Last edited by defragster; 04-18-2015 at 05:30 AM.

  20. #20
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,991
    I'm not sure at run time, but at compile time there is a unique macro defined based on the CPU (note there are 2 leading and 2 trailing underscores in the processor specific macros):

    • Teensy 3.0: __MK20DX128__
    • Teensy 3.1: __MK20DX256__
    • Teensy LC: __MKL26Z64__


    You would use it in conditional compilation:

    Code:
    #if !defined(CORE_TEENSY)
      Serial.println ("Danger Will Robinson, non-Teensy found");
    #elif !defined(__arm__)
      Serial.println ("Running on a non-arm Teensy like the 2.0/2.1++");
    #elif defined(__MKL26Z64__)
      Serial.println ("Running on a Teensy LC");
    #elif defined(__MK20DX256__)
      Serial.println ("Running on a Teensy 3.1");
    #elif defined(__MK20DX128__)
      Serial.println ("Running on a Teensy 3.0");
    #else
      Serial.println ("Running on an unknown Teensy processor");
    #endif
    Last edited by MichaelMeissner; 04-18-2015 at 01:38 PM.

  21. #21
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    107
    @defragster, post #17
    "Modified the Print to show Serial # as reported in USB (with '0' padded on the end)"
    Yes, I saw that the last 3 bytes of the Ethernet MAC address differ from the USB serialnumber by the extra trailing zero at the latter.
    From both Teensy 3.1's I have here:
    MAC address 04:E9:E5:01:45:32, reported USB serial# 832500,
    MAC address 04:E9:E5:01:45:96, reported USB serial# 833500.

    Do you have any idea why the reported USB serialnumber has an additional zero padded?

    Thanks,
    Paul


    For reference the code I use to get the MAC address:
    Code:
    uint8_t mac[6];
    
    void read(uint8_t word, uint8_t *mac, uint8_t offset) {
      FTFL_FCCOB0 = 0x41;             // Selects the READONCE command
      FTFL_FCCOB1 = word;             // read the given word of read once area
    
      // launch command and wait until complete
      FTFL_FSTAT = FTFL_FSTAT_CCIF;
      while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF));
    
      *(mac + offset) =   FTFL_FCCOB5;     // collect only the top three bytes,
      *(mac + offset + 1) = FTFL_FCCOB6;   // in the right orientation (big endian).
      *(mac + offset + 2) = FTFL_FCCOB7;   // Skip FTFL_FCCOB4 as it's always 0.
    }
    
    void read_mac() {
      read(0xe, mac, 0);
      read(0xf, mac, 3);
    }
    
    void print_mac()  {
      size_t count = 0;
      for (uint8_t i = 0; i < 6; ++i) {
        if (i != 0) count += Serial.print(":");
        count += Serial.print((*(mac + i) & 0xF0) >> 4, 16);
        count += Serial.print(*(mac + i) & 0x0F, 16);
      }
    }
    
    void setup() {
      Serial.begin(115200);
      while (!Serial);
      pinMode(13, OUTPUT);
      digitalWrite(13, HIGH); // just to show that the board is active
      delay (1000);
      Serial.print("Reading MAC address from hardware: ");
      read_mac();
      print_mac();
    }
    
    void loop() {
    }

  22. #22
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,805
    Quote Originally Posted by MichaelMeissner View Post
    processor specific macros:
    • Teensy 3.0: __MK20DX128__
    • Teensy 3.1: __MK20DX256__
    • Teensy LC: __MKL26Z64__


    You would use it in conditional compilation:
    Thanks for that compilation @MM - I've never come across it as such. Compile time makes sense since it won't cross compile&load anyhow.

    @PaulS: I just made my sample match what I saw reported in TyQt - not sure if the '0' pad is right or why, or if it will break in future.

  23. #23
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    I take it that (unlike others) Freescale ARMs don't have a unique serial number in silicon or OTP memory and so PJRC had to DIY? E.g. the STM32F4's have a 96 bit unique ID.

  24. #24
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    107
    Actually, it looks like there is unique chip serial number.
    From the datasheet:
    Click image for larger version. 

Name:	MK20DX256VLH7 datasheet page 1.png 
Views:	266 
Size:	144.9 KB 
ID:	4206
    And in the reference manual, the 4 32-bit registers that make up the 128-bit unique ID are described on page 265-267:
    Click image for larger version. 

Name:	MK20DX256VLH7 ref manual page 256.png 
Views:	208 
Size:	53.9 KB 
ID:	4207

    Unfortunately, I'm not that familiar with coding C++ to access these registers.

    Paul

  25. #25
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,991
    Quote Originally Posted by defragster View Post
    Thanks for that compilation @MM - I've never come across it as such. Compile time makes sense since it won't cross compile&load anyhow.
    Conditional compilation allows to bring in extra code that is only available on a particular machine. I use it for example to set constants for pin numbers, so for example using A3/17 for the neopixel pin on the LC, and pin 4 that I was using previously on the Teensy 3.0/3.1. I also for instance enable using EEPROM on Teensy 3.0/3.1 to save the last random number every so often to use as the seed the next time the Teensy is booted, but I don't do it on the Teensy LC, due to the implementation of EEPROM on the LC.

Posting Permissions

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