teensy 3 MAC address

Status
Not open for further replies.
The change I did was to add a call to the code that reads in the serial number, if it finds that it is going to go into HSRUN mode. I also added code into that call that made it only do stuff once. So in all other cases the current code path to call the function is still done.
 
The change I did was to add a call to the code that reads in the serial number, if it finds that it is going to go into HSRUN mode. I also added code into that call that made it only do stuff once. So in all other cases the current code path to call the function is still done.

For affected MCU's (K66 only? Unless K64 has similar issue if it OC's over 120 MHz with similar limitation?) I envisioned this as something done on 'boot' before HSRUN is active so a static copy (like you suggest 'only once') was always present? In any case with a uniform TEENSY_Ser#() the same code could be used on boot with USB, or by any 'user'.

Wondering if PJRC planning mini_beta of K64 units? Since I have K66 & Ethernet Beta boards I opted for T_3.6 SIX pack , so I won't have any K64's until they go retail.

I was AWOL 3 weeks - now back home and should be online in coming days, once I unpack.

With a uniform function() to Drop/Restore HSRUN - the end user could do this and also batch EEPROM I/O so such things can be usable. It would compromise clock specific items during that time - but better than losing functionality, or having end user hacks. With 'plenty' of RAM - some/all of the EEPROM could be cached for R/W access and quickly sync'd with :: eeprom_read_block() and eeprom_write_block() [ or _dword() ?]
 
For affected MCU's (K66 only? Unless K64 has similar issue if it OC's over 120 MHz with similar limitation?) I envisioned this as something done on 'boot' before HSRUN is active so a static copy (like you suggest 'only once') was always present? In any case with a uniform TEENSY_Ser#() the same code could be used on boot with USB, or by any 'user'.

Wondering if PJRC planning mini_beta of K64 units? Since I have K66 & Ethernet Beta boards I opted for T_3.6 SIX pack , so I won't have any K64's until they go retail.

I was AWOL 3 weeks - now back home and should be online in coming days, once I unpack.

With a uniform function() to Drop/Restore HSRUN - the end user could do this and also batch EEPROM I/O so such things can be usable. It would compromise clock specific items during that time - but better than losing functionality, or having end user hacks. With 'plenty' of RAM - some/all of the EEPROM could be cached for R/W access and quickly sync'd with :: eeprom_read_block() and eeprom_write_block() [ or _dword() ?]
Welcome back,

I think you are right that maybe there should be some caching scheme for EEPROM. In my case often I only read from the EEPROM at startup. Maybe things like Servo offsets and the like. I may then have a special mode I go into that allows me to update these settings, but again this is in an isolated portion of the code.

I have not heard anything either about T3.5 beta, but thought these might be interesting as a drop in upgrade, that still gives me 5v tolerance. Obviously one issue will be the size of the board not fitting where the T3.2 would fit. Will talk more about this on another thread. So I ordered the 2+2 Kickstarter.
 
I have not heard anything either about T3.5 beta, but thought these might be interesting as a drop in upgrade, that still gives me 5v tolerance. Obviously one issue will be the size of the board not fitting where the T3.2 would fit. Will talk more about this on another thread. So I ordered the 2+2 Kickstarter.
I suspect KurtE already knows, but others thinking about the 3.5 as a drop in replacement, the touchRead function does not work on the 3.5. It should work on the 3.6. Also, the back row of pins (Vbattery, 3.3v, ground, program, DAC) have been relocated.
 
Welcome back,

I think you are right that maybe there should be some caching scheme for EEPROM. In my case often I only read from the EEPROM at startup. Maybe things like Servo offsets and the like. I may then have a special mode I go into that allows me to update these settings, but again this is in an isolated portion of the code.

I have not heard anything either about T3.5 beta, but thought these might be interesting as a drop in upgrade, that still gives me 5v tolerance. Obviously one issue will be the size of the board not fitting where the T3.2 would fit. Will talk more about this on another thread. So I ordered the 2+2 Kickstarter.

Thanks Kurt!

Awesome to see that Paul is doing a mini_beta for T_3.5, that will pave the way for the KS shipping in good shape out of the box.

Glad you see value: Indeed EEPROM usage varies - but some supported/generalized way to use it seems important - having no HSRUN access to it could be a real loss. Reading/Caching in setup() could cover most use cases without risking destabilizing anything. Having a way to write back without reprogramming to lower speed sketch (and back) would extend the functionality especially if the data changes during run time - even if it was followed by a restart to come up stable. But if the device can sleep() and return it should be able to recover without that?

Built in SD card could supplant the EEPROM - only problem would be getting that data to new cards consistently as they come and go, or go bad.

@MM - I put overt "lack of TOUCH in the KS specs" on the 'nit' thread. I think that should be called out. Both MM and Kurt RTFM in posts 1110 & 1111 confirmed it was not just a typo where T_3.6 has TOUCH and T_3.5 does not when I posted about that.
 
Hm, ok, does this work with disabled usb and/or lower fcpu or teensy 3.2?

Frank,
I tried your code on my T3.6-r3 and get the following results:

Code:
CPU SPEED: 240MHz , COM3
MAC: 0x000000000000
Serial: 0

CPU SPEED: 180MHz , COM3
MAC: 0x000000000000
Serial: 0

CPU SPEED: 120MHz, COM6
MAC: 0x04E9E5032345
Serial: 205637

CPU SPEED: 96MHz, COM6
MAC: 0x04E9E5032345
Serial: 205637

CPU SPEED: 48MHz, No USB Emulated Serial
MAC: 0x04E9E5032345
Serial: 205637

Cmason Code / THT T3_mac.zip
CPU SPEED: 120MHz, COM6
Chip MAC ID == 04: E9: E5: 04: E9: E5
Teensy Serial# 3220210
Reading 128-bit UniqueID from Teensy 0017FFFF FFFFFFFF 4E453506 1001001E
 
Last edited:
Frank,
I tried your code on my T3.6-r3 and get the following results:

If that is your ser# I think that is as expected as it doesn't alter speed - just does the 64 bit math operations - do you have TYQT installed - It gets the ser# from Paul's boot code you could compare.

If you merged KurtE's PULL code changes I think you can emulate the timing of Paul's code before HSRUN goes active?

You might run Frank's code here in parallel at this change? : usb_init_serialnumber();

Then compare the results?

I want to try this myself - but I'm not that far unpacked yet.
 
Defragster,

TyQT V07.6 64-bit reports this serial number: 2056370
Identity: 2056370-Teensy

I tried KurtE's Core modifications, but did not see any changes, but I was looking for COM port changes, not Serial numbers.
 
Looks like it is working.

AFAIK - Windows meshes the serial into recognized USB DEVICE, when that returns 0, it is a different device. Kurt's location precedes the hsrun loss of access right?

<edit> phone edit - wrong words.
 
Last edited:
I hacked what I suggested - put FrankB's code into location suggested by KurtE's PULL - and I made subtle code change below as it is called once before HSRUN and then again twice after for my TYQT identified "2056390-Teensy":

Code:
uint64_t readMAC() {
[B]  static uint64_t mac = 0;

  if ( 0 == mac ) {[/B]

MAC: 0x04E9E5032347
Serial: 205639

CPU is T_3.6 F_CPU =120000000

MAC: 0x04E9E5032347
Serial: 205639

CPU is T_3.6 F_CPU =240000000

MAC: 0x04E9E5032347
Serial: 205639

CPU is T_3.6 F_CPU =180000000
 
Perhaps the best solution would be to read the area in the startup code, before everything else.
 
Perhaps the best solution would be to read the area in the startup code, before everything else.

Indeed that is what KurtE's code does (see post #58). But is does it for the specific purpose of setting the USB strings up just before HSRUN - so when it is needed later it is pre-saved in that storage area.

But it doesn't save it in the # only format used by FrankB's code (which won't work once HSRUN is enabled) as user code to get MAC id and serial #.

Kurt - I'm wondering it might be good save the 'num' in place of :: usb_init_serialnumber_called = 1. If that were made a public variable by PJRC - nobody would ever have to manually call code for MAC and ser#?

Code:
static uint32_t usb_init_serialnumber_called = 0;
void usb_init_serialnumber(void)
{
	char buf[11];
	uint32_t i, num;
	if (usb_init_serialnumber_called)
		return;

[URL="https://github.com/KurtE/cores/blob/4276f875c101fe43687247e4917b1cc4700d1e93/teensy3/usb_desc.c#L1219"]//  'num' collect code here[/URL]

        usb_init_serialnumber_called = num;  // NOTE - this is 32 bit and is *10 in some cases
}

NOTE: DIY boards will have 0xF's in that flash until set. And Paul said Zero was set as serial # in the K66 Proto boards, though I read this now:
MAC: 0xFFFFFFFFFFFF
Serial: 16777215
 
Discovered an anomaly? For the above I did KurtE's pre HSRUN addition. I also put FrankB's code local in the same mkdx128.c file for the above. The results in post #64 are misleading it seems

Doing NEITHER in the mkdx128.c file results in 0 being read once in HSRUN mode - as expected - and the assigned USB's COM# port changes (according to TYQT) based on the serial# and hardware USB port (once the device is removed and forgotten by TYQT).

However if EITHER is done in advance of HSRUN then BOTH work after HSRUN. So it 'seems' that HSRUN causes a 0 to be returned after reset if neither was called. If either was called - or both - before HSRUN that last returned value is returned again when HRUN mode stops it from getting 'current' data.

I followed this up additionally by removing this from KurtE's code :: // usb_init_serialnumber_called = 1;
The result is the same. Once the following is executed - repeat reads of FTFL_FCCOB# after HSRUN is set return the prior value:
Code:
    FTFL_FSTAT = FTFL_FSTAT_CCIF;
    while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) {}

Wondering if there are other such values that HSRUN affects with regard to actual versus value 'cached' or not - that is 'stale' data is being used?

I found this when I wondered if HSRUN alone caused the 'read' to fail - or if it was the subsequent clock setting. Finding the above I can confirm that after HSRUN is set - even if the clock speeds are not yet boosted over 120 MHz that the MAC/Ser# read fails. And I assume that without HSRUN {which I understand to boost the voltage, which must make EEPROM areas unsafe to touch?} putting the clock over 120MHz may cause instability without HSRUN - so to take the MCU out of HSRUN the clock would have to be set to a safe speed (120 MHz or less) to read the 4 KB of EEPROM for instance - then back to HSRUN and the clock setting restored. Though I also note that HSRUN is ALWAYS set ( SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode ) without regard to the clock speed final setting afterwards in mkdx128.c. But as expected: when the clock doesn't exceed 120 MHz it still works, but 144 MHz or above the MAC/Ser# read gets a zero - so I assume some other clock settings precede this code that change the effect of HSRUN?

AFAIK this is accurate - hopefully it is complete as far as I went, and makes sense and adds some value for this thread and any possible 'on the fly' speed changes for EEPROM or other.
 
Following up on my prior post the following code change results in a valid serial at 120, 180 and 240 MHz. Both using FrankB's prior posted code and in TYQT reading the serial number on connecting to the device.

From the empirical results above it seems making this call results in this value being made 'static/local/cached' to the processor before HSRUN goes active.
> Is this a safe assumption and a sufficient solution?
> I did not "__disable_irq(); & __enable_irq();" across this call - I do not know if the interrupts are active at this time?

On my Win10 desktop - fresh install of IDE 1.6.11 and TeensyDuino 1.30b3 and programming to my T_3.6 I made the following change at line #842 of :: arduino_16_11\hardware\teensy\avr\cores\teensy3\mk20dx128.c"


Code:
	// if we need faster than the crystal, turn on the PLL
   #if defined(__MK66FX1M0__)
    #if F_CPU > 120000000
[B]	FTFL_FCCOB0 = 0x41;
	FTFL_FCCOB1 = 0x07;
	FTFL_FSTAT = FTFL_FSTAT_CCIF;
	while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) {}
[/B]	SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode
	while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) ; // wait for HSRUN
    #endif

MAC: 0x04E9E5032347
Serial: 205639

CPU is T_3.6
F_CPU =240000000

<edit> I used FrankB's code - I see the PJRC code uses this line that may be more consistent::
*(uint32_t *)&FTFL_FCCOB3 = 0x41070000;
 
Last edited:
I've created a library that helps to retrieve the Serial and MAC from within your sketch:
...
Works with Teensy LC, Teensy 3.0 .. 3.6 and in HS_RUN-Mode.

Frank,
It's working on my T3.6-R3, tested at 24, 48, 96, 120, 180 and 240MHz.
Also TyQT and Arduino report a constant Com Port # at all speeds after running TeensyMAC

I get the following output:

Serial: 2056370
MAC: 0x04E9E5032345

Thanks
 
I was using T3Mac.h on the Teensy 3.2 and it worked without defining:
Code:
uint8_t mac[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
How does this one work?
I wonder that:
Code:
Serial.printf("MAC: 0x%012llX\n", teensyMAC());
only shows 14 digits?
What does "0x%012llX\n" do?
 
I was using T3Mac.h on the Teensy 3.2 and it worked without defining:
Code:
uint8_t mac[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
How does this one work?
I wonder that:
Code:
Serial.printf("MAC: 0x%012llX\n", teensyMAC());
only shows 14 digits?

Nope, it shows 12 digits.
Whats makes you think a MAC has more digits ?

https://en.wikipedia.org/wiki/MAC_address

Output (one of T3.2 - just tested again) :
Code:
Serial: 1679610
MAC: 0x04E9E5029019

Please post your output, if it is different.

What does "0x%012llX\n" do?
It's a format string...
http://www.cplusplus.com/reference/cstdio/printf/
 
Yes a MAC has 12 but the one you put in by hand has more.
So i wonder how to use this now in:
Code:
uint8_t mac[] =
Ethernet.begin(mac, ip, dnsServer, gateway, subnet);

From your posting in the W5500 tread it sound the Teensy has a MAC?
I thought this one reads the serial and uses this as MAC.

On Arduinos i always used a Dallas DS18B20 as MAC:
Code:
// Set MAC via DS18B20
void setupEthernet(){
  byte i;
  byte dsAddress[8];
  Serial.println( "Searching for DS18B20..." );
  oneWire.reset_search(); // Start the search with the first device
  if (!oneWire.search(dsAddress)) {
    Serial.println( "None found. Using default MAC address." );
  } else {
    Serial.println( "Success! Setting MAC address:" );
    Serial.print( " DS18B20 ROM  =" );
    for( i = 0; i < 8; i++) {
      Serial.write(' ');
      Serial.print( dsAddress[i], HEX );
    }
    Serial.println();
    // Offset array to skip DS18B20 family code, and skip mac[0]
    mac[1] = dsAddress[3];
    mac[2] = dsAddress[4];
    mac[3] = dsAddress[5];
    mac[4] = dsAddress[6];
    mac[5] = dsAddress[7];
  }

  Serial.print( " Ethernet MAC =" );
  for( i = 0; i < 6; i++ )
  {
    Serial.write( ' ' );
    Serial.print( mac[i], HEX );
  }
  Serial.println();
  startEthernet();
}
 
Yup,, the serial is part of the mac.

Perhaps try something like this ?
Code:
uint64_t mac64;
uint8_t mac[6];

mac64 = teensyMAC();
mac[0] = mac64 >> 40;
mac[1] = mac64 >> 32;
mac[2] = mac64 >> 24;
mac[3] = mac64 >> 16;
mac[4] = mac64 >> 8;
mac[5] = mac64;

Ethernet.begin( mac, ..
 
Ok after 2 hours of trying i can't figure out how to formate that thing to something like:
Code:
D0 50 99 2A 3D F6
or
D0:50:99:2A:3D:F6

Code:
uint64_t mac64;
uint8_t mac[6];

// Set MAC via Teensy serial
void setupEthernet() {
  byte i;
  Serial.println("Reading MAC from hardware..." ); 
  mac64 = teensyMAC();
  mac[0] = mac64 >> 40;
  mac[1] = mac64 >> 32;
  mac[2] = mac64 >> 24;
  mac[3] = mac64 >> 16;
  mac[4] = mac64 >> 8;
  mac[5] = mac64;
  Serial.println("Success! Setting MAC address:");
  Serial.print("  Ethernet MAC =");
  for( i = 0; i < 6; i++ ) {
    Serial.write(' ');
    Serial.print("0x");
    Serial.print(mac[i], HEX);
  }

  Serial.println();
  Serial.printf("  Test 1 = 0x%012llX\n", mac[i], HEX);
  Serial.printf("  Test 2 = 0x%012llX\n", mac[i]);
  Serial.printf("  Test 3 = 0x%012llX\n", mac64);
  Serial.printf("  Test 4 = 0x%012llX\n", teensyMAC());
  Serial.println();

  startEthernet();
}
Output:
Code:
Reading MAC from hardware...
Success! Setting MAC address:
  Ethernet MAC = 0x4 0xE9 0xE5 0x3 0xA7 0xAE
  Test 1 = 0x001000000000
  Test 2 = 0x001B00000000
  Test 3 = 0x04E9E503A7AE
  Test 4 = 0x04E9E503A7AE
 
Last edited:
Status
Not open for further replies.
Back
Top