That is already done by PJRC. Each Teensy comes with a unique MAC/Serial #
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.
#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
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
Did you get a working way to show a unique Serial # from code?
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.
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?
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;
}
I added to the existing code to pull part of the MCU id (third segment) and use that as the ID.
...