Teensy 4.1 MAC Address

Status
Not open for further replies.

KD0RC

Well-known member
I have my Teensy 4.1 working (for the most part...) but it does not seem to have a MAC address. If I feed NativeEthernet a legitimate MAC address for another device, DHCP serves up a nice ip address and my Teensy uses it to connect to my Flex SDR radio. If I want two devices on the same network segment, it only works for the last device added as the local ip is the same for both devices (I think because the MAC address is the same). Is there a trick to NativeEthernet that will give me a different ip for a second device connection? Am I approaching this problem all wrong? Is there a get MAC address function or something that will help me? I am not a network guy, so I am fumbling around with this...

Thanks,
Len
 
They do come preprogrammed with a unique MAC address, this is the code that retrieves it for a Teensy 4.x, just supply it with your MAC address array that's 6 bytes long and it'll set it accordingly:
Code:
void teensyMAC(uint8_t *mac) {
    for(uint8_t by=0; by<2; by++) mac[by]=(HW_OCOTP_MAC1 >> ((1-by)*8)) & 0xFF;
    for(uint8_t by=0; by<4; by++) mac[by+2]=(HW_OCOTP_MAC0 >> ((3-by)*8)) & 0xFF;
    Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
 
vj answered the MAC question. I can confirm each one is unique (or at least the 4 I have are).

To the IP addr question, if you select DHCP, you get unique IP addrs. (I think that's the default...) You can also specify a static IP addr but probably better to use DHCP and then reserve those addrs on your router. It plays a lot nicer with your network. You may need the MAC for that on some routers.
 
AH! Thanks VJ, I really appreciate that. I included your code in my program, and it worked! I now have two devices connected to the same SDR radio and communicating properly. I really appreciate all that you have done with the NativeEthernet library. Using it I have made huge strides in my project. Without it, I never would have gotten off the starting line.

Thanks,
Len
 
They do come preprogrammed with a unique MAC address, this is the code that retrieves it for a Teensy 4.x, just supply it with your MAC address array that's 6 bytes long and it'll set it accordingly:
Code:
void teensyMAC(uint8_t *mac) {
    for(uint8_t by=0; by<2; by++) mac[by]=(HW_OCOTP_MAC1 >> ((1-by)*8)) & 0xFF;
    for(uint8_t by=0; by<4; by++) mac[by+2]=(HW_OCOTP_MAC0 >> ((3-by)*8)) & 0xFF;
    Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

Do you think that NativeEthernet should have a constructor where this is used to instantiate the MAC address for those new at this? Or maybe just have it as a "getSystemMAC()" function? I'm just starting out with Ethernet on the Teensy 4.1 (this is actually my first time doing anything with Ethernet honestly), and I think other newcomers might want this too. Thoughts?
 
I'd agree with that. This Ethernet stuff is a bit of a black art to me. The above seems to say "just supply it with your MAC address array that's 6 bytes long" - but isn't the MAC address the thing I am trying to find out.
I would really appreciate something that I can just run and I'll work out what it means afterwards.
I'm just trying to send a simple email - which on the Raspberry Pi is straight forward - but I can't seem to find the equivalent for and Arduino or more specifically the Teensy.
 
I'm right there with you. I'm still trying to figure out which Ethernet library is the right one. Looks like a lot of documentation hasn't yet caught up to the 4.1 release.

Which library are you using? Got it working yet? I have 2 T4.1's here that I'm trying to get to chat to each other.
 
I'd agree with that. This Ethernet stuff is a bit of a black art to me. The above seems to say "just supply it with your MAC address array that's 6 bytes long" - but isn't the MAC address the thing I am trying to find out.
I would really appreciate something that I can just run and I'll work out what it means afterwards.
I'm just trying to send a simple email - which on the Raspberry Pi is straight forward - but I can't seem to find the equivalent for and Arduino or more specifically the Teensy.

That need to send the 'address array' is where the Teensy's MAC will be written when the code shown above is executed. 'just supply' means allocate the needed 6 byte variable and pass to the function shown in p#2 and it returns with the device MAC.


I'm right there with you. I'm still trying to figure out which Ethernet library is the right one. Looks like a lot of documentation hasn't yet caught up to the 4.1 release.

Which library are you using? Got it working yet? I have 2 T4.1's here that I'm trying to get to chat to each other.

The library that works for the T_4.1 AFAIK ( no it is not noted with ethernet on the T_4.1 page ) is :: (arduino)\hardware\teensy\avr\libraries\NativeEthernet
Check the examples - it works like prior libraries for ethernet - though there is a thread for that library indicating it maps into a more powerful underlying code (IIRC FNET?) that can be used directly.
 
Hi All

I didn't realise that the Teensy 4.1 had a MAC address burned into its eFUSEs until reading this thread so I read out the eFUSEs on my board:

eFUSEs
======
LOCK
0x40528107
CFG
0x677f0555
0x184c71d2
0x500000bb
0x00420002
0x00000000
0x00080018
0x00000000
MEM
0x00000000
0x00009400
0x0000007c
0x00000000
0x00000000
ANALOG
0x00000000
0x51d4b65f
0x00000000
SRK
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
SJC
0x00000000
0x00000000
MAC (locked)
0xe50d301a
0x000004e9
0x00000000
GP
0x00000000
0x00000000
SW GP
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
MISC
0x00000040
0x00000000
REVOKE
0x00000000
PATCH
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
GP3
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000


where it is seen that the MAC address is set and locked so that it can't be modified in any way.

In the IEEE list of organizationally unique identifiers PJRC is registered as owner of the block of 16M that the addresses are defined from.

04-E9-E5 (hex) PJRC.COM, LLC
04E9E5 (base 16) PJRC.COM, LLC
14723 SW Brooke Ct
Sherwood Oregon 97140
US


Since there is a registered OUI but without confidentiality (which costs $3'565 a year at the moment) I presume that PJRC invested $3'085 in this block of addresses (or had done so earlier for assigning MAC addresses to previous products too).
The MAC address probably contributes to the price of the board so I think that it makes sense in using it for the intended reasons that this cost is not wasted ;-)

Regards

Mark
 
Share ROM dump code?

Any chance you would be willing to share the code you used to scrape the eFUSE registers from T4.1?

Hi All

I didn't realise that the Teensy 4.1 had a MAC address burned into its eFUSEs until reading this thread so I read out the eFUSEs on my board:

eFUSEs
======
LOCK
0x40528107
CFG
0x677f0555
0x184c71d2
0x500000bb
0x00420002
0x00000000
0x00080018
0x00000000
MEM
0x00000000
0x00009400
0x0000007c
0x00000000
0x00000000
ANALOG
0x00000000
0x51d4b65f
0x00000000
SRK
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
SJC
0x00000000
0x00000000
MAC (locked)
0xe50d301a
0x000004e9
0x00000000
GP
0x00000000
0x00000000
SW GP
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
MISC
0x00000040
0x00000000
REVOKE
0x00000000
PATCH
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
GP3
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000


where it is seen that the MAC address is set and locked so that it can't be modified in any way.

In the IEEE list of organizationally unique identifiers PJRC is registered as owner of the block of 16M that the addresses are defined from.

04-E9-E5 (hex) PJRC.COM, LLC
04E9E5 (base 16) PJRC.COM, LLC
14723 SW Brooke Ct
Sherwood Oregon 97140
US


Since there is a registered OUI but without confidentiality (which costs $3'565 a year at the moment) I presume that PJRC invested $3'085 in this block of addresses (or had done so earlier for assigning MAC addresses to previous products too).
The MAC address probably contributes to the price of the board so I think that it makes sense in using it for the intended reasons that this cost is not wasted ;-)

Regards

Mark
 
Since there is a registered OUI but without confidentiality (which costs $3'565 a year at the moment) I presume that PJRC invested $3'085 in this block of addresses (or had done so earlier for assigning MAC addresses to previous products too).

Yes, I can confirm PJRC registered with IEEE several years ago for a 24 bit OUI.
 
Hi

Below is the code that I use which you may be able to reverse engineer to your environment. It is from the uTasker project so uses different headers and formatted output commands.
If you just want to read the values on your board you can simply load the iHex from here to do it https://www.utasker.com/iMX/Teensy_4_1.html - just command "eFUSE" in the Administrator menu (menu 4) to get it to print them out over the USB

Code:
        {
            int i;
            volatile unsigned long *ptrRegister = HW_OCOTP_CFG0_ADD;
            POWER_UP_ATOMIC(2, OCOTP_CTRL_CLOCK);
            fnDebugMsg("eFUSEs\r\n======\r\nLOCK\r\n");
            fnDebugHex(HW_OCOTP_LOCK, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugMsg("CFG\r\n");
            i = 7;
            while (i-- != 0) {
                fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
                ptrRegister += 4;
            }
            fnDebugMsg("MEM\r\n");
            ptrRegister = HW_OCOTP_MEM0_ADD;
            i = 5;
            while (i-- != 0) {
                fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
                ptrRegister += 4;
            }
            fnDebugMsg("ANALOG\r\n");
            ptrRegister = HW_OCOTP_ANA0_ADD;
            i = 3;
            while (i-- != 0) {
                fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
                ptrRegister += 4;
            }
            fnDebugMsg("SRK\r\n");
            ptrRegister = HW_OCOTP_SRK0_ADD;
            i = 8;
            while (i-- != 0) {
                fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
                ptrRegister += 4;
            }
            fnDebugMsg("SJC\r\n");
            fnDebugHex(HW_OCOTP_SJC_RESP0, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugHex(HW_OCOTP_SJC_RESP1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugMsg("MAC");
            if ((HW_OCOTP_LOCK & eFUSE_LOCK_MAC_ADDR_LOCK_MASK) != 0) {
                fnDebugMsg(" (locked)\r\n");
            }
            else {
                fnDebugMsg("\r\n");
            }
            fnDebugHex(HW_OCOTP_MAC0, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugHex(HW_OCOTP_MAC1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
    #if defined HW_OCOTP_MAC2
            fnDebugHex(HW_OCOTP_MAC2, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugMsg("GP\r\n");
    #else
            fnDebugMsg("GP\r\n");
            fnDebugHex(HW_OCOTP_GP3, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
    #endif
            fnDebugHex(HW_OCOTP_GP1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugHex(HW_OCOTP_GP2, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugMsg("SW GP\r\n");
            ptrRegister = HW_OCOTP_SW_GP1_ADD;
            i = 5;
            while (i-- != 0) {
                fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
                ptrRegister += 4;
            }
            fnDebugMsg("MISC\r\n");
            fnDebugHex(HW_OCOTP_MISC_CONF0, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugHex(HW_OCOTP_MISC_CONF1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
            fnDebugMsg("REVOKE\r\n");
            fnDebugHex(HW_OCOTP_SRK_REVOKE, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
    #if defined HW_OCOTP_ROM_PATCH0
            fnDebugMsg("PATCH\r\n");
            ptrRegister = HW_OCOTP_ROM_PATCH0_ADD;
            i = 8;
            while (i-- != 0) {
                fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
                ptrRegister += 4;
            }
            fnDebugMsg("GP3\r\n");
            ptrRegister = HW_OCOTP_GP30_ADD;
            i = 8;
            while (i-- != 0) {
                fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
                ptrRegister += 4;
            }
            POWER_DOWN_ATOMIC(2, OCOTP_CTRL_CLOCK);
    #endif
        }

Note that the uTasker project simulates the i.MX RT 1062 and the Teensy board as well as the eFUSEs - I have a video showing the simulation of this and the security module in the chip (allowing XiP on-the-fly decryption to be used on the Teensy 4.1 too - without actually needing to program the eFUSEs): https://youtu.be/o7hQbOqhJoc

Regards

Mark
 
Awesome Mark, thank you! uTasker looks like an interesting project, I'll check out the links and info you mentioned.

Cheers!

/b/
 
Status
Not open for further replies.
Back
Top