teensy 3 MAC address

Status
Not open for further replies.

cmason

Well-known member
After a conversation with Paul, I think I've figured out how to access the unique Ethernet media access (MAC) address burnt into the Teensy3. This number will be different on every teensy 3, and isn't overwritten by the bootloader flashing process like the EEPROM is.

Given this class:

Code:
/** Retrieve Ethernet MAC from Teensy 3 */
class mac_addr : public Printable {
public:
    uint8_t m[6];

    mac_addr() : m({0}) {
        // Retrieve the 6 byte MAC address Paul burnt into two 32 bit words
        // at the end of the "READ ONCE" area of the flash controller.
        read(0xe,0);
        read(0xf,3);
    }

    void read(uint8_t word, uint8_t loc) {

        // To understand what's going on here, see
        // "Kinetis Peripheral Module Quick Reference" page 85 and
        // "K20 Sub-Family Reference Manual" page 548.

        FTFL_FCCOB0 = 0x41;             // Selects the READONCE command
        FTFL_FCCOB1 = word;             // read the given word of read once area
                                        // -- this is one half of the mac addr.
        FTFL_FSTAT = FTFL_FSTAT_CCIF;   // Launch command sequence
        while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) {
                                        // Wait for command completion
        }
        *(m+loc) =   FTFL_FCCOB5;       // collect only the top three bytes,
        *(m+loc+1) = FTFL_FCCOB6;       // in the right orientation (big endian).
        *(m+loc+2) = FTFL_FCCOB7;       // Skip FTFL_FCCOB4 as it's always 0.
    }

    virtual size_t printTo(Print & p) const {
        size_t count = 0;
        for(uint8_t i = 0; i < 6; ++i) {
            if (i!=0) count += p.print(":");
            count += p.print((*(m+i) & 0xF0) >> 4, 16);
            count += p.print(*(m+i) & 0x0F, 16);
        }
        return count;
    }
};

You can print out the MAC like:
Code:
Serial.print("MAC: ");
mac_addr mac;
Serial.println(mac);

On mine, this prints:
Code:
MAC: 04:E9:E5:00:0D:59

I hope Paul can verify my work here. This number at least seems to line up with the PJRC IEEE registration.

Hope this is useful.

-c
 
Last edited:
Thank you cmason. It works well for me. I removed the C++ stuff and made a small Ardiono Sketch (see attachment).
 

Attachments

  • T3_readmac.zip
    1.3 KB · Views: 1,714
I just stumbled upon this. This is great as it can be used as copy protection system. Is there anything like this available on the Teensy 2?
 
Is that an ethernet address or a generic IEEE OUI that's not coded as in the Ethernet MAC range?
IEEE 802.11 and 802.15.4 radios have a MAC in the OUI range, with MSBs to say which family.

This chip-unique number helps a great deal with devices like WizNet Ethernet devices that have no factory assigned MAC address.
 
Shortly before releasing Teensy 3.0, PJRC registered for an IEEE OUI usable for Ethernet. Every Teensy 3.0 and 3.1 has been programmed with this OUI and an incrementing 24 bit serial number. It was specifically intended for the Ethernet library with Wiznet chips.

If you use cmason's code, I would recommend disabling interrupts within the read() function. You might also want to declare read() as static, to avoid possible conflicts with such a generic function name possibly being used in any other files.
 
I have been using the version posted by user THT in post #2. The Teensy3 ID has served perfectly as an Ethernet MAC for the WIZ820io so I can register more that one Teensy3 on my network using Bonjour without having to worry about a conflict.
 
If need be on the Teensy2 et al that have no S/N, you can use the IEEE 'self administered' MAC address range.
If I recall correctly, its a 0x02 in the MSByte.
With that bit on, you can use any bits you wish and no manufacturer's MAC will conflict.
 
Shortly before releasing Teensy 3.0, PJRC registered for an IEEE OUI usable for Ethernet. Every Teensy 3.0 and 3.1 has been programmed with this OUI and an incrementing 24 bit serial number. It was specifically intended for the Ethernet library with Wiznet chips.
Another good but not well known thing!
 
thanks headroom,steve. That THT-cmason sketch is great, just pulled the mac out. now going to use this for the wiznet module.
 
Last edited:
additional changes

After a conversation with Paul, I think I've figured out how to access the unique Ethernet media access (MAC) address burnt into the Teensy3. This number will be different on every teensy 3, and isn't overwritten by the bootloader flashing process like the EEPROM is.

Given this class:
------- snip -------
Hope this is useful.

-c

I made a few changes to this, here is the results:
Code:
// macAddress.h
#ifndef _MACADDR_H_
#define _MACADDR_H_

/** Retrieve Ethernet MAC from Teensy 3 */

/*
 from http://forum.pjrc.com/threads/91-teensy-3-MAC-address 
 Edited by: Gene Reeves 04/23/2014
	* added [] operator
	* added uint8_t * operator for use in Ethernet.begin()
*/

class macAddress : public Printable {
protected:
    uint8_t _m[6];
public:
    macAddress() : _m({0}) {
        // Retrieve the 6 byte MAC address Paul burnt into two 32 bit words
        // at the end of the "READ ONCE" area of the flash controller.
        read(0xe,0);
        read(0xf,3);
    }
	
	// gives access to individual elements 
	uint8_t operator[](int index) const {return _m[index];}
	uint8_t& operator[](int index) {return _m[index];}
	
    // gives access to uint8_t array, use like this: Ethernet.begin(mac_address)
	operator uint8_t *() {return &(_m[0]);}

    void read(uint8_t word, uint8_t loc) {

        // To understand what's going on here, see
        // "Kinetis Peripheral Module Quick Reference" page 85 and
        // "K20 Sub-Family Reference Manual" page 548.

        cli();
        FTFL_FCCOB0 = 0x41;             // Selects the READONCE command
        FTFL_FCCOB1 = word;             // read the given word of read once area
                                        // -- this is one half of the mac addr.
        FTFL_FSTAT = FTFL_FSTAT_CCIF;   // Launch command sequence
        while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) {
                                        // Wait for command completion
        }
        *(_m+loc) =   FTFL_FCCOB5;       // collect only the top three bytes,
        *(_m+loc+1) = FTFL_FCCOB6;       // in the right orientation (big endian).
        *(_m+loc+2) = FTFL_FCCOB7;       // Skip FTFL_FCCOB4 as it's always 0.
        sei();
    }

    virtual size_t printTo(Print & p) const {
        size_t count = 0;
        for(uint8_t i = 0; i < 6; ++i) {
            if (i!=0) count += p.print(":");
            count += p.print((*(_m+i) & 0xF0) >> 4, 16);
            count += p.print(*(_m+i) & 0x0F, 16);
        }
        return count;
    }
    friend class EthernetClass;
    friend class UDP;
    friend class Client;
    friend class Server;
    friend class DhcpClass;
    friend class DNSClient;
};
#endif

with the above code you can do this:
Code:
macAddress myMac;
// print our MAC
Serial.print("My MAC is ");
Serial.println(myMac);

Serial.println("Starting Network using DHCP.");

if (Ethernet.begin(myMac)==0)
{
    Serial.println("Failed to acquire IP address using DHCP, halting.");
    while(1) {;}
}
Serial.print("My IP is ");
Serial.println(Ethernet.localIP());
//
// rest of your code here

Hope someone finds this useful. :cool:

if you see anything that does not look correct, please post a reply,
Gene_R
 
Per Paul's suggestion in December, you should probably be disabling interrupts around the manipulation of the flash.
 
Paul: this unique Ethernet MAC address is absolutely perfect for what I am doing, and solves a gigantic issue for me!
--THANK YOU!--
Now all I need to do is write the CDC EEM code and attach it to my IP stack! You rock!
 
Arduino IDE formatted library.

Just unpack into your arduino library dir and enjoy.
 

Attachments

  • T3Mac.zip
    1.6 KB · Views: 1,291
Is the K20 burnt with the MAC address or the MINI54T (bootloader) that then gets loaded into the K20?
 
IIRC the MAC address ins burnt into the K20. It has a small write-once memory area where the MAC is stored.
 
This is not working with Teensy 3.1. Is it supposed to? I was hoping it would help me with using the SD Card and Wiznet820io which work separately but not together despite trying various CS pins. I will post this on a different thread, none of which have helped me get these working together.
 
Yes, this works on the Teensy 3.1 as well and Ethernet is one of the reason for the existence of the burned in code. This works perfectly with the WIZ820io. I have not tinkered around with SD card stuff yet, but you'll find many references to SD card related problems on the forum.
It depends often on the specific SD card used.

Why would the MAC burned into the K20 help you with the SD card ?
 
Last edited:
Ive just tried the zip file mentioned,
and I'm getting an error on #include <Arduion.h> on the T3_readmac example.

Anything I should obviously do apart from cry !!

I know this is an old thread, so is there a different way of getting the MAC number off a teensy 3.2 ?
 
it should compile without errors. Have you put the lib into your lib folder and restarted arduino IDE?
 
Even re booted the PC

here is the sketch

#include "T3Mac.h"

void setup() {
delay(1000);
Serial.begin(57600);

Serial.println("Reading MAC from hardware...");
read_mac();

Serial.print("MAC: ");
print_mac();
Serial.println();

Serial.print("Finished.");
}

void loop() {
}




and this is the message

In file included from T3_readmac.ino:1:0:
C:\Users\A123456\Documents\Arduino\libraries\T3Mac/T3Mac.h:4:21: warning: extra tokens at end of #include directive [enabled by default]
#include <Arduino.h>;
^
In file included from C:\Users\A123456\Documents\Arduino\libraries\T3Mac\T3Mac.cpp:1:0:
C:\Users\A123456\Documents\Arduino\libraries\T3Mac\T3Mac.h:4:21: warning: extra tokens at end of #include directive [enabled by default]
#include <Arduino.h>;
 
Even re booted the PC

<snip\>

and this is the message

In file included from T3_readmac.ino:1:0:
C:\Users\A123456\Documents\Arduino\libraries\T3Mac/T3Mac.h:4:21: warning: extra tokens at end of #include directive [enabled by default]
#include <Arduino.h>;
^
In file included from C:\Users\A123456\Documents\Arduino\libraries\T3Mac\T3Mac.cpp:1:0:
C:\Users\A123456\Documents\Arduino\libraries\T3Mac\T3Mac.h:4:21: warning: extra tokens at end of #include directive [enabled by default]
#include <Arduino.h>;

this one is too easy!
remove the semicolon at the end of the #include line.
(the compiler suggested that this token is too much)
 
Last edited:
Status
Not open for further replies.
Back
Top