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

Thread: Custom Teensy Write Once Memory "Burn" Direction needed

  1. #1
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94

    Custom Teensy Write Once Memory "Burn" Direction needed

    I have been searching for some time about any information on how to "burn" a MAC address/Serial into a fixed spot on the MK20 Chip. I would like to uniquely identify the chip without having the ability to change it again. Thanks

  2. #2
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,059
    That is already done by PJRC. Each Teensy comes with a unique MAC/Serial #

  3. #3
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    Quote Originally Posted by Theremingenieur View Post
    That is already done by PJRC. Each Teensy comes with a unique MAC/Serial #
    I believe this is the case with Teensy Purchased from authorized sources. However I purchased the Bootloader chip from pjrc but sourced my own MK20 Chip. I believe the its the MK20 chip that has the "burned" serial number in it? I did run a MAC script from the forum and all I get is the FF:FF:FF...... response.

  4. #4
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    I have reached the next phase of my project and looking for answers on how to set the unique ID on my custom Teensy based boards. One main reason is the USB uses this to uniquely identify it. My project will use multiple USB connections and each of them using the 4294967295 (highest number) as its intentity is throwing my software off. I could go in and perhaps change some of the way the USB library sends this info while uploading code but it complicates things when I need to use a common firmware among multiple boards. Any help on how to set this would be appreciated. I recall that this field is also a write once and cannot be changed.

  5. #5
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,066
    Indeed write once area - not seen it explained - though it is in the Manual

    A quick fix might be to go into the USB segment where the number is read and return a unique number. You could put one into EEPROM on each and read and return that to keep them unique from the same source code?

    If you edit this : usb_init_serialnumber(void) in usb_desc.c that should work.

    Perhaps edit at the end and something like "if (num == 4294967295 )" then read from the prepared EEPROM space and use that number?

    I did another test the other day and EEPROM read seemed to be usable at the early time when USB was being woke.


    I thought about that when I got the Alpha T_3.6 board that didn't get a Serial# written but never did it.

  6. #6
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    Quote Originally Posted by defragster View Post
    Indeed write once area - not seen it explained - though it is in the Manual

    A quick fix might be to go into the USB segment where the number is read and return a unique number. You could put one into EEPROM on each and read and return that to keep them unique from the same source code?

    If you edit this : usb_init_serialnumber(void) in usb_desc.c that should work.

    Perhaps edit at the end and something like "if (num == 4294967295 )" then read from the prepared EEPROM space and use that number?

    I did another test the other day and EEPROM read seemed to be usable at the early time when USB was being woke.


    I thought about that when I got the Alpha T_3.6 board that didn't get a Serial# written but never did it.
    Thanks defragster! That is probably what I will need to do. Very good suggestion! I also found some code on pulling the UUID of the chip so I have some method to utilize that in creating unique ID's etc.

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,066
    UID :: Yeah - I found that once too - lots of bits!:
    Code:
    #ifndef __MKL26Z64__  // Seems valid for T_3.x family
    	unsigned long chipNum[4] = { SIM_UIDH, SIM_UIDMH, SIM_UIDML, SIM_UIDL };
    #else // T_LC skips one value
    	unsigned long chipNum[4] = { 0L, SIM_UIDMH, SIM_UIDML, SIM_UIDL };
    #endif

  8. #8
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    Quote Originally Posted by defragster View Post
    UID :: Yeah - I found that once too - lots of bits!:
    Code:
    #ifndef __MKL26Z64__  // Seems valid for T_3.x family
    	unsigned long chipNum[4] = { SIM_UIDH, SIM_UIDMH, SIM_UIDML, SIM_UIDL };
    #else // T_LC skips one value
    	unsigned long chipNum[4] = { 0L, SIM_UIDMH, SIM_UIDML, SIM_UIDL };
    #endif
    Yes! I don't dare just use one block.... Hmmmm

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,066
    Did you get a working way to show a unique Serial # from code?

  10. #10
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    Quote Originally Posted by defragster View Post
    Did you get a working way to show a unique Serial # from code?
    Yes! and thank you! It will be better anyways. My code is on my work machine I will need to post what I was able to do but just as you suggest I added a if statement and told it to use a custom number if all values were FF: etc.. I have not incorporated reading values from eeprom yet but it should work ok.

  11. #11
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,066
    Great to know it works.

    If you try EEPROM you might use what I did here: Configure-USB-after-sketch-has-already-loaded

    Working in the core's c code the EEPROM wasn't visible when built - so I put the function shown there in my sketch and called that from the core code. Then it seemed to be getting called about 50 times during USB enumeration - so as noted later I should have made that read just the first time to a static and return the static each time after the first when it was set. Where this code is on serial # read won't likely have that repeating issue.

    The other good thing is this offers a work around so you might get BOLD and read the manual on writing the one time area with a serial number, and worst case mess up a processor or two and have to have those continue to use this software correction. I never tried it because I didn't have that 'luxury' so I didn't want to try without a good reason. If you do that would be nice to see.

  12. #12
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    Quote Originally Posted by defragster View Post
    Great to know it works.

    If you try EEPROM you might use what I did here: Configure-USB-after-sketch-has-already-loaded

    Working in the core's c code the EEPROM wasn't visible when built - so I put the function shown there in my sketch and called that from the core code. Then it seemed to be getting called about 50 times during USB enumeration - so as noted later I should have made that read just the first time to a static and return the static each time after the first when it was set. Where this code is on serial # read won't likely have that repeating issue.

    The other good thing is this offers a work around so you might get BOLD and read the manual on writing the one time area with a serial number, and worst case mess up a processor or two and have to have those continue to use this software correction. I never tried it because I didn't have that 'luxury' so I didn't want to try without a good reason. If you do that would be nice to see.
    Finally getting to trying out the eeprom read. I see your code in the other example as a void function. I am not clear yet on how to call it into the core code from my sketch and making it a static, this is good stuff and is what I need to learn more . Thanks!

  13. #13
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,664
    Maybe I should consider an edit to the USB code, to have it return a serial number based on NXP/Freescale's unique IDs when the program-once memory is blank?

  14. #14
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    Quote Originally Posted by PaulStoffregen View Post
    Maybe I should consider an edit to the USB code, to have it return a serial number based on NXP/Freescale's unique IDs when the program-once memory is blank?
    That would be fantastic for those with custom Teensy boards! In my case I will be having several on a USB hub and need an efficient way to have each one with their own "ID". EEPROM is one way (still working on it) but I like your suggestion even better.

    crees

  15. #15
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,066
    That would be better than void (-1 ) info as the Ser# is used by TyCommander. I wondered about doing that but wasn't sure how the bits mapped to get a unique number

  16. #16
    Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    94
    I added to the existing code to pull part of the MCU id (third segment) and use that as the ID. This is found around line 1451 from usb_desc.c

    This section basically checks the location where the teensy serial number is written (write once memory) If it reads FFFFFFFF (4294967295) then its a MCU without a teensy SN. If true then it will use part of the 32 bit SIM_UIDML MCU ID

    There are examples of the MCU ID that I have pulled from different boards.

    Array 128-bit UniqueID from chip: 95710000-E0CD002F-002C5008-49634E45
    Array 128-bit UniqueID from chip: 95710000-E0CD002F-000D5008-49634E45

    The part that changes and is unique is the third set (SIM_UIDML)




    Code:
    void usb_init_serialnumber(void)
    {
    	char buf[11];
    	uint32_t i, num;
    
    	__disable_irq();
    #if defined(HAS_KINETIS_FLASH_FTFA) || defined(HAS_KINETIS_FLASH_FTFL)
    	FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
    	FTFL_FCCOB0 = 0x41;
    	FTFL_FCCOB1 = 15;
    	FTFL_FSTAT = FTFL_FSTAT_CCIF;
    	while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
    	num = *(uint32_t *)&FTFL_FCCOB7;
    	
    	//If num = FFFFFFFF.. then we must have a MCU that has no burned serial number (Custom Teensy?)
    	//if so lets use SIM_UIDML (part of MCU Serial Number) instead
    	if (num == 4294967295) {
    		num = SIM_UIDML;
    	}
    
    #elif defined(HAS_KINETIS_FLASH_FTFE)
    	kinetis_hsrun_disable();
    	FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
    	*(uint32_t *)&FTFL_FCCOB3 = 0x41070000;
    	FTFL_FSTAT = FTFL_FSTAT_CCIF;
    	while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
    	num = *(uint32_t *)&FTFL_FCCOBB;
    	kinetis_hsrun_enable();
    	//unsigned char mpcnum[num];
    	
    	//If num = FFFFFFFF.. then we must have a MCU that has no burned serial number (Custom Teensy?)
    	//if so lets use SIM_UIDML (part of MCU Serial Number) instead
    	if (num == 4294967295) {
    	num = SIM_UIDML;
    	}
    #endif
    	__enable_irq();
    	// 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;
    }
    Last edited by crees; 11-27-2018 at 07:06 AM.

Posting Permissions

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