In a device running µC/TCP-IP, a MAC address can be obtained from a number of different sources.
If you're using the µC/TCP-IP network stack to develop a product that is destined to reside on a wired Ethernet network, then the stack will need to have a means of obtaining a hardware, or MAC (Media Access Control) address for your product. (Much the same can be said for a device that will be used on wireless, 802.11-based networks, but we'll focus on wired Ethernet for now, to keep the conversion a bit clearer.) Ultimately, your product's address will need to come from the IEEE; every Ethernet-based product must have a globally unique address, and the IEEE manages the address pool. However, there are a few different mechanisms via which µC/TCP-IP can become aware of your address.
Why does the stack need to be supplied with your device's MAC address in the first place? Oftentimes, this address must be written to your hardware platform's Ethernet controller so that the controller can properly perform its intended function of sending and receiving packets of data. Some controllers, for example, automatically stamp outgoing Ethernet frames with a source address that is expected to be written to their registers before data exchange begins. In controllers that lack such capabilities, it is still necessary that µC/TCP-IP itself have the address for the benefit of its Ethernet-related code. This code implements link-layer operations that do not vary according to the underlying hardware, such as verification of the destination address of received frames.
It's possible for your application code to provide a MAC address directly to the TCP/IP stack via a function call, to
NetIF_AddrHW_Set(). However, if such a call is not present, then responsibility for establishing an address typically falls to the underlying Ethernet controller driver. During an application's call to the TCP/IP initialization function
NetIF_Start(), an Ethernet driver typically checks for an address in a few different places.
Most of the drivers developed by Micriµm begin by looking for an address in the contents of the configuration file
net_dev_cfg.c. This file is expected to declare a data structure of type NET_DEV_CFG_ETHER that can be used to adjust a number of driver-related parameters, including the MAC address. When you specify your device's address via
net_dev_cfg.c, you can use a valid, IEEE-provided address, or, in a controlled testing environment, simply make up an address.
In the case that the data structure in
net_dev_cfg.c contains a valid address, most drivers will use that address. If, however, it contains
"00:00:00:00:00:00", or is simply null, then another address source will be needed. The next step for a driver is often to check whether an address was already provided by application code, via the above-mentioned
NetIF_AddrHW_Set() function. Your application can use this call to load an address from a non-volatile storage device that is not configured to automatically load your Ethernet controller's registers.
NetIF_AddrHW_Set() can also be called when an application needs to override the address provided by the final source that most drivers check, the Ethernet controller itself.
On some hardware platforms, a MAC address is automatically provided to the Ethernet controller from an EEPROM or another non-volatile storage device. In other words, on these platforms, no call to
NetIF_AddrHW_Set() is necessary in application code in order to load the address from the storage device. The driver for such a platform will actually call an internal version of
NetIF_AddrW_Set() to alert the TCP/IP stack of the address already established in the Ethernet controller.
An overview of the steps taken by a typical driver to obtain an address is provided in the above diagram. There are at least a few drivers from Micriµm that add extra steps to this sequence, but most, at a minimum, query the sources shown here when seeking an address. To determine the steps taken by a specific driver, you can review the descriptive comment blocks preceding the functions that comprise that driver's source code. (Within most drivers, the code for establishing an address can be found in the "start" function.) For additional information on µC/TCP-IP itself, including descriptions of the API calls and configuration parameters mentioned in the preceding paragraphs, you can consult the stack's online documentation.
Matt Gordon is Micrium's Director of Application Engineering.