Merge branch 'feature/base_mac_address' into 'master'

Optimize configuration of base MAC address

Application developer can call APIs to configure base MAC address
instead of using menuconfig.

See merge request !744
This commit is contained in:
Ivan Grokhotkov 2017-05-11 12:01:51 +08:00
commit c742f7d860
12 changed files with 350 additions and 126 deletions

View file

@ -152,49 +152,36 @@ config MEMMAP_SPISRAM
The ESP32 can control an external SPI SRAM chip, adding the memory it contains to the
main memory map. Enable this if you have this hardware and want to use it in the same
way as on-chip RAM.
choice BASE_MAC_ADDRESS_STORAGE
prompt "Storage of the base MAC address"
default BASE_MAC_STORED_DEFAULT_EFUSE
help
Select storage of the base MAC address which is used for all network interfaces when networking is initialized.
If "Default place in EFUSE" is selected, esp32 will use the base MAC address which is written into default
place in EFUSE when the chip is manufactured.
If "Customer-defined place in EFUSE" is selected, ESP32 will use customer-defined base MAC address which
is written into EFUSE Block 3 words 0, 1.
If "Other customer-defined place" is selected, esp32 will use customer-defined base MAC address from other
place(flash, EEPROM, etc). User code must call esp_base_mac_addr_set_external to set the base MAC address
before network features are initialised.
config BASE_MAC_STORED_DEFAULT_EFUSE
bool "Default place in EFUSE"
config BASE_MAC_STORED_CUSTOMER_DEFINED_EFUSE
bool "Customer-defined place in EFUSE"
config BASE_MAC_STORED_OTHER_CUSTOMER_DEFINED_PLACE
bool "Other customer-defined place"
endchoice
choice NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
bool "Number of MAC address generated from the hardware MAC address in efuse"
default FOUR_MAC_ADDRESS_FROM_EFUSE
choice NUMBER_OF_UNIVERSAL_MAC_ADDRESS
bool "Number of universally administered (by IEEE) MAC address"
default FOUR_UNIVERSAL_MAC_ADDRESS
help
Config the number of MAC address which is generated from the base MAC address in efuse.
If the number is two, the MAC addresses of WiFi station and bluetooth are generated from
the base MAC address in efuse. The MAC addresses of WiFi softap and ethernet are derived
from that of WiFi station and bluetooth respectively.
If the number is four, the MAC addresses of WiFi station, WiFi softap, bluetooth and ethernet
are all generated from the base MAC address in efuse.
Configure the number of universally administered (by IEEE) MAC addresses.
During initialisation, MAC addresses for each network interface are generated or derived from a
single base MAC address.
If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap,
Bluetooth and Ethernet) receive a universally administered MAC address. These are generated
sequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address.
If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth)
receive a universally administered MAC address. These are generated sequentially by adding 0
and 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet)
receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC
addresses, respectively.
When using the default (Espressif-assigned) base MAC address, either setting can be used. When using
a custom universal MAC address range, the correct setting will depend on the allocation of MAC
addresses in this range (either 2 or 4 per device.)
config TWO_MAC_ADDRESS_FROM_EFUSE
config TWO_UNIVERSAL_MAC_ADDRESS
bool "Two"
config FOUR_MAC_ADDRESS_FROM_EFUSE
config FOUR_UNIVERSAL_MAC_ADDRESS
bool "Four"
endchoice
config NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
config NUMBER_OF_UNIVERSAL_MAC_ADDRESS
int
default 2 if TWO_MAC_ADDRESS_FROM_EFUSE
default 4 if FOUR_MAC_ADDRESS_FROM_EFUSE
default 2 if TWO_UNIVERSAL_MAC_ADDRESS
default 4 if FOUR_UNIVERSAL_MAC_ADDRESS
config SYSTEM_EVENT_QUEUE_SIZE
int "System event queue size"

View file

@ -37,6 +37,8 @@ typedef int32_t esp_err_t;
#define ESP_ERR_TIMEOUT 0x107
#define ESP_ERR_INVALID_RESPONSE 0x108
#define ESP_ERR_INVALID_CRC 0x109
#define ESP_ERR_INVALID_VERSION 0x10A
#define ESP_ERR_INVALID_MAC 0x10B
#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */

View file

@ -31,9 +31,9 @@ typedef enum {
ESP_MAC_ETH,
} esp_mac_type_t;
#define TWO_MAC_ADDRESS_FROM_EFUSE 2
#define FOUR_MAC_ADDRESS_FROM_EFUSE 4
#define NUM_MAC_ADDRESS_FROM_EFUSE CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
#define TWO_UNIVERSAL_MAC_ADDR 2
#define FOUR_UNIVERSAL_MAC_ADDR 4
#define UNIVERSAL_MAC_ADDR_NUM CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS
/**
* @attention application don't need to call this function anymore. It do nothing and will
@ -103,60 +103,84 @@ uint32_t system_get_free_heap_size(void) __attribute__ ((deprecated));
uint32_t esp_random(void);
/**
* @brief Set base MAC address from external storage e.g. flash and EEPROM.
* @brief Set base MAC address with the MAC address which is stored in BLK3 of EFUSE or
* external storage e.g. flash and EEPROM.
*
* Base MAC address is used to generate the MAC addresses used by the networking interfaces.
* If using base MAC address stored in external storage, call this API to set base MAC
* address from external storage before initializing WiFi/BT/Ethernet.
* If using base MAC address stored in BLK3 of EFUSE or external storage, call this API to set base MAC
* address with the MAC address which is stored in BLK3 of EFUSE or external storage before initializing
* WiFi/BT/Ethernet.
*
* @param mac base MAC address, length: 6 bytes.
*
* @return ESP_OK on success
*/
esp_err_t esp_base_mac_addr_set_external(uint8_t *mac);
esp_err_t esp_base_mac_addr_set(uint8_t *mac);
/**
* @brief Return base MAC address set using esp_mac_addr_set_external.
* @brief Return base MAC address which is set using esp_base_mac_addr_set.
*
* @param mac base MAC address, length: 6 bytes.
*
* @return ESP_OK on success
* ESP_ERR_INVALID_MAC base MAC address has not been set
*/
esp_err_t esp_base_mac_addr_get(uint8_t *mac);
/**
* @brief Return base MAC address which was previously written to BLK3 of EFUSE.
*
* Base MAC address is used to generate the MAC addresses used by the networking interfaces.
* If using base MAC address stored in external storage, call this API to set base MAC
* address from external storage before initializing WiFi/BT/Ethernet.
* This API returns the custom base MAC address which was previously written to BLK3 of EFUSE.
* Writing this EFUSE allows setting of a different (non-Espressif) base MAC address. It is also
* possible to store a custom base MAC address elsewhere, see esp_base_mac_addr_set() for details.
*
* @param mac base MAC address, length: 6 bytes.
*
* @return ESP_OK on success
* ESP_ERR_INVALID_VERSION An invalid MAC version field was read from BLK3 of EFUSE
* ESP_ERR_INVALID_CRC An invalid MAC CRC was read from BLK3 of EFUSE
*/
esp_err_t esp_efuse_mac_get_custom(uint8_t *mac);
/**
* @brief Return base MAC address which is factory-programmed by Espressif in BLK0 of EFUSE.
*
* @param mac base MAC address, length: 6 bytes.
*
* @return ESP_OK on success
*/
esp_err_t esp_base_mac_addr_get_external(uint8_t *mac);
esp_err_t esp_efuse_mac_get_default(uint8_t *mac);
/**
* @brief Read hardware MAC address from efuse.
*
* In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC
* calculated from ESP32 station MAC.
* So users need to call esp_wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed.
* Function has been renamed to esp_efuse_mac_get_default.
* This name will be removed in a future release.
*
* @param mac hardware MAC address, length: 6 bytes.
*
* @return ESP_OK on success
*/
esp_err_t esp_efuse_read_mac(uint8_t* mac);
esp_err_t esp_efuse_read_mac(uint8_t *mac) __attribute__ ((deprecated));
/**
* @brief Read hardware MAC address.
*
* Function has been renamed to esp_efuse_read_mac.
* Function has been renamed to esp_efuse_mac_get_default.
* This name will be removed in a future release.
*
* @param mac hardware MAC address, length: 6 bytes.
* @return ESP_OK on success
*/
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated));
esp_err_t system_efuse_read_mac(uint8_t *mac) __attribute__ ((deprecated));
/**
* @brief Read hardware MAC address and set MAC address of the interface.
* @brief Read base MAC address and set MAC address of the interface.
*
* This function first reads hardware MAC address from efuse. Then set the MAC address of the interface
* including wifi station, wifi softap, bluetooth and ethernet.
* This function first get base MAC address using esp_base_mac_addr_get or reads base MAC address
* from BLK0 of EFUSE. Then set the MAC address of the interface including wifi station, wifi softap,
* bluetooth and ethernet.
*
* @param mac MAC address of the interface, length: 6 bytes.
* @param type type of MAC address, 0:wifi station, 1:wifi softap, 2:bluetooth, 3:ethernet.
@ -166,32 +190,20 @@ esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated));
esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type);
/**
* @brief Derive MAC address.
* @brief Derive local MAC address from universal MAC address.
*
* This function derives a local MAC address from an universal MAC address.
* Addresses can either be universally administered addresses or locally administered addresses.
* A universally administered address is uniquely assigned to a device by its manufacturer.
* The first three octets (in transmission order) identify the organization that issued the identifier
* and are known as the Organizationally Unique Identifier (OUI).[4] The remainder of the address
* (three octets for MAC-48 and EUI-48 or five for EUI-64) are assigned by that organization in nearly
* any manner they please, subject to the constraint of uniqueness. A locally administered address is
* assigned to a device by a network administrator, overriding the burned-in address.
* Universally administered and locally administered addresses are distinguished by setting
* the second-least-significant bit of the first octet of the address. This bit is also referred to
* as the U/L bit, short for Universal/Local, which identifies how the address is administered.
* If the bit is 0, the address is universally administered. If it is 1, the address is locally administered.
* In the example address 06-00-00-00-00-00 the first octet is 06 (hex), the binary form of which is 00000110,
* where the second-least-significant bit is 1. Therefore, it is a locally administered address.[7] Consequently,
* this bit is 0 in all OUIs.
* In ESP32, universal MAC address is generated from the hardware MAC address in efuse.
* A `definition of local vs universal MAC address can be found on Wikipedia
* <https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local>`.
* In ESP32, universal MAC address is generated from base MAC address in EFUSE or other external storage.
* Local MAC address is derived from the universal MAC address.
*
* @param dst_mac Derived local MAC address, length: 6 bytes.
* @param src_mac Source universal MAC address, length: 6 bytes.
* @param local_mac Derived local MAC address, length: 6 bytes.
* @param universal_mac Source universal MAC address, length: 6 bytes.
*
* @return ESP_OK on success
*/
esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac);
esp_err_t esp_derive_local_mac(uint8_t* local_mac, const uint8_t* universal_mac);
/**
* Get SDK version

View file

@ -221,7 +221,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
return ESP_ERR_INVALID_SIZE;
}
uint8_t sta_mac[6];
esp_efuse_read_mac(sta_mac);
esp_efuse_mac_get_default(sta_mac);
if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) {
ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \
MACSTR ", found " MACSTR,
@ -252,7 +252,7 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
return err;
}
uint8_t sta_mac[6];
esp_efuse_read_mac(sta_mac);
esp_efuse_mac_get_default(sta_mac);
err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
if (err != ESP_OK) {
return err;

View file

@ -36,63 +36,50 @@
static const char* TAG = "system_api";
static uint8_t ext_base_mac_addr[6] = {0};
static uint8_t base_mac_addr[6] = { 0 };
void system_init()
{
}
esp_err_t esp_base_mac_addr_set_external(uint8_t *mac)
esp_err_t esp_base_mac_addr_set(uint8_t *mac)
{
if (mac == NULL) {
ESP_LOGE(TAG, "External base MAC address is NULL");
ESP_LOGE(TAG, "Base MAC address is NULL");
abort();
}
memcpy(ext_base_mac_addr, mac, 6);
memcpy(base_mac_addr, mac, 6);
return ESP_OK;
}
esp_err_t esp_base_mac_addr_get_external(uint8_t *mac)
esp_err_t esp_base_mac_addr_get(uint8_t *mac)
{
uint8_t null_mac[6] = {0};
if (memcmp(ext_base_mac_addr, null_mac, 6) == 0) {
ESP_LOGE(TAG, "External MAC address is not set");
abort();
if (memcmp(base_mac_addr, null_mac, 6) == 0) {
ESP_LOGI(TAG, "Base MAC address is not set, read default base MAC address from BLK0 of EFUSE");
return ESP_ERR_INVALID_MAC;
}
memcpy(mac, ext_base_mac_addr, 6);
memcpy(mac, base_mac_addr, 6);
return ESP_OK;
}
esp_err_t esp_efuse_read_mac(uint8_t* mac)
esp_err_t esp_efuse_mac_get_custom(uint8_t *mac)
{
uint32_t mac_low;
uint32_t mac_high;
uint8_t efuse_crc;
uint8_t calc_crc;
#ifdef CONFIG_BASE_MAC_STORED_DEFAULT_EFUSE
mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
mac[0] = mac_high >> 8;
mac[1] = mac_high;
mac[2] = mac_low >> 24;
mac[3] = mac_low >> 16;
mac[4] = mac_low >> 8;
mac[5] = mac_low;
efuse_crc = mac_high >> 16;
#else
uint8_t version = REG_READ(EFUSE_BLK3_RDATA5_REG) >> 24;
if (version != 1) {
ESP_LOGE(TAG, "Customer efuse MAC address version error, version = %d", version);
abort();
ESP_LOGE(TAG, "Base MAC address from BLK3 of EFUSE version error, version = %d", version);
return ESP_ERR_INVALID_VERSION;
}
mac_low = REG_READ(EFUSE_BLK3_RDATA1_REG);
@ -106,7 +93,34 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac)
mac[5] = mac_low >> 16;
efuse_crc = mac_high;
#endif //CONFIG_BASE_MAC_STORED_DEFAULT_EFUSE
calc_crc = esp_crc8(mac, 6);
if (efuse_crc != calc_crc) {
ESP_LOGE(TAG, "Base MAC address from BLK3 of EFUSE CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
return ESP_ERR_INVALID_CRC;
}
return ESP_OK;
}
esp_err_t esp_efuse_mac_get_default(uint8_t* mac)
{
uint32_t mac_low;
uint32_t mac_high;
uint8_t efuse_crc;
uint8_t calc_crc;
mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
mac[0] = mac_high >> 8;
mac[1] = mac_high;
mac[2] = mac_low >> 24;
mac[3] = mac_low >> 16;
mac[4] = mac_low >> 8;
mac[5] = mac_low;
efuse_crc = mac_high >> 16;
calc_crc = esp_crc8(mac, 6);
@ -118,30 +132,31 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac)
return ESP_OK;
}
} else {
ESP_LOGE(TAG, "MAC address CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
ESP_LOGE(TAG, "Base MAC address from BLK0 of EFUSE CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
abort();
}
}
return ESP_OK;
}
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__((alias("esp_efuse_read_mac")));
esp_err_t system_efuse_read_mac(uint8_t *mac) __attribute__((alias("esp_efuse_mac_get_default")));
esp_err_t esp_efuse_read_mac(uint8_t *mac) __attribute__((alias("esp_efuse_mac_get_default")));
esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac)
esp_err_t esp_derive_mac(uint8_t* local_mac, const uint8_t* universal_mac)
{
uint8_t idx;
if (dst_mac == NULL || src_mac == NULL) {
if (local_mac == NULL || universal_mac == NULL) {
ESP_LOGE(TAG, "mac address param is NULL");
return ESP_ERR_INVALID_ARG;
}
memcpy(dst_mac, src_mac, 6);
memcpy(local_mac, universal_mac, 6);
for (idx = 0; idx < 64; idx++) {
dst_mac[0] = src_mac[0] | 0x02;
dst_mac[0] ^= idx << 2;
local_mac[0] = universal_mac[0] | 0x02;
local_mac[0] ^= idx << 2;
if (memcmp(dst_mac, src_mac, 6)) {
if (memcmp(local_mac, universal_mac, 6)) {
break;
}
}
@ -159,50 +174,46 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
}
if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_ETH) {
ESP_LOGE(TAG, "mac type is incorrect");
ESP_LOGE(TAG, "mac type is incorrect");
return ESP_ERR_INVALID_ARG;
}
_Static_assert(NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE \
|| NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE, \
_Static_assert(UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR \
|| UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR, \
"incorrect NUM_MAC_ADDRESS_FROM_EFUSE value");
#if defined(CONFIG_BASE_MAC_STORED_DEFAULT_EFUSE) || defined(CONFIG_BASE_MAC_STORED_CUSTOMER_DEFINED_EFUSE)
esp_efuse_read_mac(efuse_mac);
#endif
#if defined(CONFIG_BASE_MAC_STORED_OTHER_CUSTOMER_DEFINED_PLACE)
esp_base_mac_addr_get_external(efuse_mac);
#endif
if (esp_base_mac_addr_get(efuse_mac) != ESP_OK) {
esp_efuse_mac_get_default(efuse_mac);
}
switch (type) {
case ESP_MAC_WIFI_STA:
memcpy(mac, efuse_mac, 6);
break;
case ESP_MAC_WIFI_SOFTAP:
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
memcpy(mac, efuse_mac, 6);
mac[5] += 1;
}
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
esp_derive_mac(mac, efuse_mac);
}
break;
case ESP_MAC_BT:
memcpy(mac, efuse_mac, 6);
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
mac[5] += 2;
}
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
mac[5] += 1;
}
break;
case ESP_MAC_ETH:
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
memcpy(mac, efuse_mac, 6);
mac[5] += 3;
}
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
efuse_mac[5] += 1;
esp_derive_mac(mac, efuse_mac);
}

View file

@ -0,0 +1,77 @@
Base MAC address
================
Overview
--------
Serveral universally administered(by IEEE) MAC addresses are uniquely assigned to the networking interfaces(WiFi/BT/Ethernet).
The final octet of each universally administered MAC address increases by one. Only the first one which is called base MAC address
of them is stored in EFUSE or external storage, the others are generated from it. Here, 'generate' means adding 0, 1, 2 and 3
(respectively) to the final octet of the base MAC address.
If the universally administered MAC addresses are not enough for all of the networking interfaces. Local administered MAC addresses
which are derived from universally administered MAC addresses are assigned to the reset of networking interfaces.
A `definition of local vs universal MAC address can be found on Wikipedia<https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local>`.
The number of universally administered MAC address can be configured using ``make menuconfig``.
Base MAC address
^^^^^^^^^^^^^^^^
If using the default base MAC address factory programmed by Espressif in BLK0 of EFUSE, nothing needs to be done.
If using a custom base MAC address stored in BLK3 of EFUSE, call API esp_efuse_mac_get_custom() to get the base MAC address
which is stored in BLK3 of EFUSE. If correct MAC address is returned, then call esp_base_mac_addr_set() to set the base MAC
address for system to generate the MAC addresses used by the networking interfaces(WiFi/BT/Ethernet).
There are 192 bits storage spaces for custom to store base MAC address in BLK3 of EFUSE. They are EFUSE_BLK3_RDATA0,
EFUSE_BLK3_RDATA1, EFUSE_BLK3_RDATA2, EFUSE_BLK3_RDATA3, EFUSE_BLK3_RDATA4 and EFUSE_BLK3_RDATA5, each of them is 32 bits
register. The format of the 192 bits storage spaces is:
------------------------------------------------------
Field |Bits |Range |Description
------------------------------------------------------
version |8 |[191:184] |1: useful. 0: useless
------------------------------------------------------
reserve |112 |[183:72] |reserved
------------------------------------------------------
mac address |64 |[71:8] |base MAC address
------------------------------------------------------
mac crc |8 |[7:0] |crc of base MAC address
------------------------------------------------------
If using base MAC address stored in external storage, firstly get the base MAC address stored in external storage, then call
API esp_base_mac_addr_set() to set the base MAC address for system to generate the MAC addresses used by the networking
interfaces(WiFi/BT/Ethernet).
All of the steps must be done before initializing the networking interfaces(WiFi/BT/Ethernet). It is recommended to do it in
app_main() which can be referenced in example `system/base_mac_address`.
Number of universally administered MAC address
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth) receive a universally
administered MAC address. These are generated sequentially by adding 0 and 1 (respectively) to the base MAC address.
The remaining two interfaces (WiFi softap and Ethernet) receive local MAC addresses. These are derived from the universal
WiFi station and Bluetooth MAC addresses, respectively.
If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap, Bluetooth and Ethernet)
receive a universally administered MAC address. These are generated sequentially by adding 0, 1, 2 and 3 (respectively)
to the final octet of the base MAC address.
When using the default (Espressif-assigned) base MAC address, either setting can be used. When using a custom universal MAC
address range, the correct setting will depend on the allocation of MAC addresses in this range (either 2 or 4 per device.)
API Reference
-------------
Header Files
^^^^^^^^^^^^
* :component_file:`esp32/include/esp_system.h`
Functions
---------
.. doxygenfunction:: esp_base_mac_addr_set
.. doxygenfunction:: esp_efuse_mac_get_custom

View file

@ -10,6 +10,7 @@ System API
Over The Air Updates (OTA) <ota>
Deep Sleep <deep_sleep>
Logging <log>
Base MAC address <base_mac_address>
Example code for this API section is provided in :example:`system` directory of ESP-IDF examples.

View file

@ -0,0 +1,9 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := base_mac_address
include $(IDF_PATH)/make/project.mk

View file

@ -0,0 +1,4 @@
# Example: base mac address
This example illustrates how to get and set base MAC address.

View file

@ -0,0 +1,42 @@
menu "Example Configuration"
choice BASE_MAC_ADDRESS_STORAGE
prompt "Storage of the base MAC address"
default BASE_MAC_STORED_EFUSE_BLK0
help
Select storage of the base MAC address which is used to generate MAC addresses of all network interfaces
when networking is initialized.
If "Default (Espressif factory) EFUSE BLK0" is selected, esp32 will use default base MAC address which is
written into EFUSE block 0 words 1, 2 when the chip is manufactured.
If "Custom EFUSE BLK3" is selected, ESP32 will use customer-defined base MAC address which is written into
EFUSE Block 3 words 0, 1. Users must call esp_efuse_mac_get_custom to get base MAC address and
esp_base_mac_addr_set to set the base MAC address before network interfaces are initialised.
If "Other external storage" is selected, esp32 will use customer-defined base MAC address from external
storage(flash, EEPROM, etc). Users must get the base MAC address first and call esp_base_mac_addr_set to
set the base MAC address before network interfaces are initialised.
config BASE_MAC_STORED_EFUSE_BLK0
bool "Default (Espressif factory) EFUSE BLK0"
config BASE_MAC_STORED_EFUSE_BLK3
bool "Custom EFUSE BLK3"
config BASE_MAC_STORED_OTHER_EXTERNAL_STORAGE
bool "Other external storage"
endchoice
choice BASE_MAC_STORED_EFUSE_BLK3_ERROR_BEHAVIOR
prompt "Read base MAC address from BLK3 of EFUSE error behavior"
depends on BASE_MAC_STORED_EFUSE_BLK3
default BASE_MAC_STORED_EFUSE_BLK3_ERROR_USE_DEFAULT
help
Select behavior when reading base MAC address from BLK3 of EFUSE error.
If "Abort" is selected, esp32 will abort.
If "Use base MAC address from BLK3 of EFUSE" is selected, esp32 will use the base MAC address which is
written into EFUSE block 0 words 1, 2 when the chip is manufactured.
config BASE_MAC_STORED_EFUSE_BLK3_ERROR_ABORT
bool "Abort"
config BASE_MAC_STORED_EFUSE_BLK3_ERROR_USE_DEFAULT
bool "Use base MAC address from BLK3 of EFUSE"
endchoice
endmenu

View file

@ -0,0 +1,76 @@
/* Base mac address example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_system.h"
#define TAG "BASE_MAC"
#ifdef CONFIG_BASE_MAC_STORED_OTHER_EXTERNAL_STORAGE
/* This is an example to show getting base MAC address from other external storage (flash, EEPROM, etc). */
static esp_err_t external_storage_mac_get(uint8_t *mac)
{
uint8_t external_storage_mac_addr[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
if (mac == NULL) {
ESP_LOGE(TAG, "The mac parameter is NULL");
abort();
}
memcpy(mac, external_storage_mac_addr, 6);
return ESP_OK;
}
#endif//CONFIG_BASE_MAC_STORED_OTHER_EXTERNAL_STORAGE
void app_main()
{
#if defined(CONFIG_BASE_MAC_STORED_EFUSE_BLK3) || defined(CONFIG_BASE_MAC_STORED_OTHER_EXTERNAL_STORAGE)
uint8_t mac_addr[8] = {0};
esp_err_t ret = ESP_OK;
#ifdef CONFIG_BASE_MAC_STORED_EFUSE_BLK3
/* Get base MAC address from BLK3 of EFUSE */
ret = esp_efuse_mac_get_custom(mac_addr);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Get base MAC address from BLK3 of EFUSE error");
/* If get custom base MAC address error, the application developer can decide what to do:
* abort or use the default base MAC address which is stored in BLK0 of EFUSE by doing
* nothing.
*/
#ifdef CONFIG_BASE_MAC_STORED_EFUSE_BLK3_ERROR_ABORT
abort();
#else
ESP_LOGI(TAG, "Use base MAC address which is stored in BLK0 of EFUSE");
#endif//CONFIG_BASE_MAC_STORED_EFUSE_BLK3_ERROR_ABORT
}
else {
esp_base_mac_addr_set(mac_addr);
ESP_LOGI(TAG, "Use base MAC address which is stored in BLK3 of EFUSE");
}
#endif//CONFIG_BASE_MAC_STORED_EFUSE_BLK3
#ifdef CONFIG_BASE_MAC_STORED_OTHER_EXTERNAL_STORAGE
/* the application developer can get base MAC address which is stored in other external
* storage (flash, EEPROM, etc) by calling some functions here.
*/
ret = external_storage_mac_get(mac_addr);
if (ret == ESP_OK) {
esp_base_mac_addr_set(mac_addr);
ESP_LOGI(TAG, "Use base MAC address which is stored in other external storage(flash, EEPROM, etc)");
}
else {
ESP_LOGI(TAG, "Use base MAC address which is stored in BLK0 of EFUSE");
}
#endif//CONFIG_BASE_MAC_STORED_OTHER_EXTERNAL_STORAGE
#else
ESP_LOGI(TAG, "Use base MAC address which is stored in BLK0 of EFUSE");
#endif//CONFIG_BASE_MAC_STORED_EFUSE_BLK3 || CONFIG_BASE_MAC_STORED_OTHER_EXTERNAL_STORAGE
}

View file

@ -0,0 +1,3 @@
#
# Main Makefile. This is basically the same as a component makefile.
#