3 weeks, 1 day ago.

How to change MAC address of non LPC1768 based boards?

Hi,

I have been trying to migrate a LPC1768 based board to STM32F407. One issue I ran into is how to set MAC address. The previous working solution somehow only works on LPC1768.

extern "C" void mbed_mac_address(char *mac)
{
    mac[0] = 0x00;
    mac[1] = 0x02;
    mac[2] = 0xf7;
    mac[3] = 0xf2;
    mac[4] = 0x04;
    mac[5] = 0xa7;
}

When I tried to build on ARCH_MAX, NUCLEO-F429ZI, FRDM_K64F, I get error:

L6200E: Symbol mbed_mac_address multiply defined (by ../../build/source/main-http.K64F.o and ../../build/mbed-os/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/TARGET_FRDM/mbed_overrides.K64F.o).

A previous post didn't mention having problems on K64F though. https://os.mbed.com/forum/bugs-suggestions/topic/31870/

1 Answer

3 weeks, 1 day ago.

Hello Zhiyong,

The mbed_mac_address(char* mac) function (defined in mbed-os\platform\sourceplatform\mbed_interface.c as WEAK) is for the STM32 target boards overridden in the mbed-os\features\netsocket\emac-drivers\TARGET_STM\stm32xx_emac.cpp file as follows:

stm32xx_emac.cpp

...

void mbed_mac_address(char *mac)
{
    if (mbed_otp_mac_address(mac)) {
        return;
    } else {
        mbed_default_mac_address(mac);
    }
    return;
}

__weak uint8_t mbed_otp_mac_address(char *mac)
{
    return 0;
}

...

That allows us to change the MAC address for the STM32 boards by defining our uint8_t mbed_otp_mac_address(char *mac) function (it will override the __weak mbed_otp_mac_address function defined by STM). For example:

main.cpp

#include "mbed.h"
#include "EthernetInterface.h"

...

uint8_t mbed_otp_mac_address(char *mac)
{
    mac[0] = 0x00;
    mac[1] = 0x02;
    mac[2] = 0xf7;
    mac[3] = 0xf2;
    mac[4] = 0x04;
    mac[5] = 0xa7;

    return 1;
}

...

int main(void)
{

...

}


For the K64F target board the mbed_mac_address(char* mac) function is overridden in the mbed-os\targets\TARGET_Freescale\TARGET_MCUXpresso_MCUS\TARGET_MCU_K64F\TARGET_FRDM\mbed_overrides.c file as follows:

mbed_overrides.c

...

void mbed_mac_address(char *mac)
{
    uint16_t MAC[3];                        // 3 16 bits words for the MAC

    // get UID via SIM_UID macros defined in the K64F MCU CMSIS header file
    uint32_t UID[4];
    UID[0] = SIM->UIDH;
    UID[1] = SIM->UIDMH;
    UID[2] = SIM->UIDML;
    UID[3] = SIM->UIDL;

    // generate three CRC16's using different slices of the UUID
    MAC[0] = crcSlow((const uint8_t *)UID, 8);  // most significant half-word
    MAC[1] = crcSlow((const uint8_t *)UID, 12);
    MAC[2] = crcSlow((const uint8_t *)UID, 16); // least significant half word

    // The network stack expects an array of 6 bytes
    // so we copy, and shift and copy from the half-word array to the byte array
    mac[0] = MAC[0] >> 8;
    mac[1] = MAC[0];
    mac[2] = MAC[1] >> 8;
    mac[3] = MAC[1];
    mac[4] = MAC[2] >> 8;
    mac[5] = MAC[2];

    // We want to force bits [1:0] of the most significant byte [0]
    // to be "10"
    // http://en.wikipedia.org/wiki/MAC_address

    mac[0] |= 0x02; // force bit 1 to a "1" = "Locally Administered"
    mac[0] &= 0xFE; // force bit 0 to a "0" = Unicast
}

...

Unfortunately, that does not allow us to change the MAC address for the K64F target.

Later on I found I can change MAC address of STM32 based boards like this:

    char mac[] = {0x00, 0x02, 0xf7, 0xf2, 0x04, 0xA8};
    mbed_mac_address(mac);

I didn't try this on K64F though.

posted by Zhiyong Li 24 Nov 2019

That compiles but doesn't change the MAC address of STM32 boards. A code like below shows unchanged MAC address:

    char mac[] = {0x00, 0x02, 0xf7, 0xf2, 0x04, 0xA8};
    mbed_mac_address(mac);

    const char* myMac = net->get_mac_address();
    printf("MAC address: %s\r\n", myMac ? myMac : "None");
posted by Zoltan Hudak 24 Nov 2019

Not quite sure why this happens. But the MAC shown to router appears to be the changed one.

posted by Zhiyong Li 29 Nov 2019