FreeRTOS_IPInit function Variable MAC Address

Hi,

I am working on a project where I need to make the MAC address variable such that my ucontroller is connected to a chip which has 32bit unique ID. I read this 32bit ID into a buffer and then I want to use this 32bit ID for MAC Address.

The problem is FreeRTOS_IPInit function takes a const MAC address as shown in the following declaration in FreeRTOS_IP.h file.

BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );

When I modify the above function by removing “const” term. I can pass the 32bit ID and can initialize the IP stack. I can even see my board gets IP address assigned by the DHCP, however when I try to communicate with Development board (TM4C129E). My Putty/YAT terminal says the connection refused. YAT terminal gives me following message;
<Warning: An existing connection was forcibly closed by the remote host>

Please note, if I do not modify the above function and rather use a const MAC address. Everything works perfect and I can talk to my board using Putty/YAT Terminal.

Any hint or any alternative approach that can make me accomplish it?

Regards,
Abid

Store the ID in a persistent (static) buffer and you should be fine. The const buffer of the MAC address buffer implies that the buffer must not change after IPInit because I think it’s not copied ‘into’ the stack but the provided data is just used (by reference). You might check the stack sources if this assumption is right.
I assume the unique chip ID is truly unique. Otherwise … strange things might happen.

Hartmut, thanks for getting into this!

I think it’s not copied ‘into’ the stack but the
provided data is just used (by reference)

Yes it is copied into a safe place:

    /* The MAC address is stored in the start of the default packet
    header fragment, which is used when sending UDP packets. */
    memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress,  ipMAC_ADDRESS_LENGTH_BYTES );

ipLOCAL_MAC_ADDRESS points to a structure owned by the IP-stack. So the bytes are stored, not the address.

Normally, for commercial products, a special MAC chip is mounted onto the board. It gives an administered, globally unique MAC address. The chip normally has a simple 1-wire access.

If you make up your own MAC-address, please look at e.g. this Wiki page about MAC addresses.

So unless your unique ID is a real MAC address, please set the lower to bis of the first byte to 0x02.

I do not see why you need to change the const-ness of the ucMACAddress parameter?
And I don’t see neither why it would change anything to its behaviour.

What happens is the following:

int main()
{
    /* No need for const here. The bytes will be copied into another buffer. */
    uint8_t ucMACAddress[ 6 ];
    /* Your function reads the unique ID. */
    read_unique_ID( ucMACAddress );
    /* Initialise the IP-stack. ucMACAddress is casted to const uint8_t*
    in the call. */
    FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGateway, ucDNS, ucMACAddress );
    /* And start the scheduler. */
    vTaskStartScheduler();
}

After FreeRTOS_IPInit: the MAC-address ( stored in ipLOCAL_MAC_ADDRESS ) will be written into the MAC registers of the EMAC, so your device gets an address.

As it is now, a FreeRTOS+TCP project takes a MAC address at start-up and never changes this address.

Summary: it makes no difference whether your MAC-address is defined with #define ( configMAC_ADDR0 ), or dynamically obtained before calling FreeRTOS_IPInit().

2 Likes