Merge branch 'feature/api_to_define_user_mac_addres' into 'master'

esp_hw_support: Adds APIs to define user own MAC addresses without generation from the base MAC address

Closes IDFGH-5534 and IDFGH-8022

See merge request espressif/esp-idf!21036
This commit is contained in:
Konstantin Kondrashov
2022-11-17 15:26:35 +08:00
13 changed files with 249 additions and 64 deletions

View File

@@ -20,6 +20,18 @@ menu "Hardware Settings"
config ESP_MAC_ADDR_UNIVERSE_ETH config ESP_MAC_ADDR_UNIVERSE_ETH
bool bool
config ESP_MAC_ADDR_UNIVERSE_IEEE802154
bool
config ESP_MAC_UNIVERSAL_MAC_ADDRESSES_ONE
bool
config ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
bool
config ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
bool
# Insert chip-specific MAC config # Insert chip-specific MAC config
rsource "./port/$IDF_TARGET/Kconfig.mac" rsource "./port/$IDF_TARGET/Kconfig.mac"
endmenu endmenu

View File

@@ -24,6 +24,9 @@ typedef enum {
ESP_MAC_BT, ESP_MAC_BT,
ESP_MAC_ETH, ESP_MAC_ETH,
ESP_MAC_IEEE802154, ESP_MAC_IEEE802154,
ESP_MAC_BASE,
ESP_MAC_EFUSE_FACTORY,
ESP_MAC_EFUSE_CUSTOM,
} esp_mac_type_t; } esp_mac_type_t;
/** @cond */ /** @cond */
@@ -128,6 +131,8 @@ esp_err_t esp_efuse_mac_get_default(uint8_t *mac);
* Then calculates the MAC address of the specific interface requested, * Then calculates the MAC address of the specific interface requested,
* refer to ESP-IDF Programming Guide for the algorithm. * refer to ESP-IDF Programming Guide for the algorithm.
* *
* The MAC address set by the esp_iface_mac_addr_set() function will not depend on the base MAC address.
*
* @param mac base MAC address, length: 6 bytes/8 bytes. * @param mac base MAC address, length: 6 bytes/8 bytes.
* length: 6 bytes for MAC-48 * length: 6 bytes for MAC-48
* 8 bytes for EUI-64(used for IEEE 802.15.4) * 8 bytes for EUI-64(used for IEEE 802.15.4)
@@ -157,6 +162,34 @@ esp_err_t esp_read_mac(uint8_t *mac, esp_mac_type_t type);
*/ */
esp_err_t esp_derive_local_mac(uint8_t *local_mac, const uint8_t *universal_mac); esp_err_t esp_derive_local_mac(uint8_t *local_mac, const uint8_t *universal_mac);
/**
* @brief Set custom MAC address of the interface. This function allows you to overwrite the MAC addresses
* of the interfaces set by the base MAC address.
*
* @param mac MAC address, length: 6 bytes/8 bytes.
* length: 6 bytes for MAC-48
* 8 bytes for EUI-64(used for ESP_MAC_IEEE802154 type)
* @param type Type of MAC address
*
* @return ESP_OK on success
*/
esp_err_t esp_iface_mac_addr_set(const uint8_t *mac, esp_mac_type_t type);
/**
* @brief Return the size of the MAC type in bytes.
*
* If CONFIG_IEEE802154_ENABLED is set then for these types:
* ESP_MAC_IEEE802154, ESP_MAC_BASE, ESP_MAC_EFUSE_FACTORY and ESP_MAC_EFUSE_CUSTOM the MAC size is 8 bytes.
* If CONFIG_IEEE802154_ENABLED is not set then for all types it returns 6 bytes.
*
* @param type Type of MAC address
*
* @return 0 MAC type not found (not supported)
* 6 bytes for MAC-48.
* 8 bytes for EUI-64.
*/
size_t esp_mac_addr_len_get(esp_mac_type_t type);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -12,10 +12,7 @@
/* esp_system.h APIs relating to MAC addresses */ /* esp_system.h APIs relating to MAC addresses */
#if CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR || \ #if CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR || \
CONFIG_ESP32C2_UNIVERSAL_MAC_ADDRESSES_FOUR || \
CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR
#define MAC_ADDR_UNIVERSE_BT_OFFSET 2 #define MAC_ADDR_UNIVERSE_BT_OFFSET 2
#else #else
#define MAC_ADDR_UNIVERSE_BT_OFFSET 1 #define MAC_ADDR_UNIVERSE_BT_OFFSET 1
@@ -26,39 +23,129 @@
#else #else
#define ESP_MAC_ADDRESS_LEN 6 #define ESP_MAC_ADDRESS_LEN 6
#endif #endif
static const char *TAG = "system_api"; static const char *TAG = "system_api";
static uint8_t base_mac_addr[ESP_MAC_ADDRESS_LEN] = { 0 }; typedef enum {
STATE_INIT = 0,
STATE_SET = (1 << 0),
} state_t;
typedef struct {
esp_mac_type_t type: 4;
state_t state: 4;
uint8_t len;
uint8_t mac[ESP_MAC_ADDRESS_LEN];
} mac_t;
static mac_t s_mac_table[] = {
#ifdef CONFIG_ESP32_WIFI_ENABLED
{ESP_MAC_WIFI_STA, STATE_INIT, 6, {0}},
{ESP_MAC_WIFI_SOFTAP, STATE_INIT, 6, {0}},
#endif
#ifdef CONFIG_ESP_MAC_ADDR_UNIVERSE_BT
{ESP_MAC_BT, STATE_INIT, 6, {0}},
#endif
{ESP_MAC_ETH, STATE_INIT, 6, {0}},
#ifdef CONFIG_ESP_MAC_ADDR_UNIVERSE_IEEE802154
{ESP_MAC_IEEE802154, STATE_INIT, 8, {0}},
#endif
{ESP_MAC_BASE, STATE_INIT, ESP_MAC_ADDRESS_LEN, {0}},
{ESP_MAC_EFUSE_FACTORY, STATE_INIT, ESP_MAC_ADDRESS_LEN, {0}},
{ESP_MAC_EFUSE_CUSTOM, STATE_INIT, ESP_MAC_ADDRESS_LEN, {0}},
};
#define ITEMS_IN_MAC_TABLE (sizeof(s_mac_table) / sizeof(mac_t))
static esp_err_t generate_mac(uint8_t *mac, uint8_t *base_mac_addr, esp_mac_type_t type);
static int get_idx(esp_mac_type_t type)
{
for (int idx = 0; idx < ITEMS_IN_MAC_TABLE; idx++) {
if (s_mac_table[idx].type == type) {
return idx;
}
}
ESP_LOGE(TAG, "mac type is incorrect (not found)");
return -1;
}
static esp_err_t get_mac_addr_from_mac_table(uint8_t *mac, unsigned idx, bool silent)
{
if (!(s_mac_table[idx].state & STATE_SET)) {
esp_mac_type_t type = s_mac_table[idx].type;
if (type == ESP_MAC_BASE || type == ESP_MAC_EFUSE_FACTORY || type == ESP_MAC_EFUSE_CUSTOM) {
esp_err_t err = ESP_OK;
if (type == ESP_MAC_BASE || type == ESP_MAC_EFUSE_FACTORY) {
err = esp_efuse_mac_get_default(s_mac_table[idx].mac);
} else if (type == ESP_MAC_EFUSE_CUSTOM) {
err = esp_efuse_mac_get_custom(s_mac_table[idx].mac);
}
if (err != ESP_OK) {
return err;
}
s_mac_table[idx].state = STATE_SET;
} else {
if (!silent) {
ESP_LOGE(TAG, "MAC address (type %d) is not set in mac table", type);
}
return ESP_ERR_INVALID_MAC;
}
}
memcpy(mac, s_mac_table[idx].mac, s_mac_table[idx].len);
return ESP_OK;
}
size_t esp_mac_addr_len_get(esp_mac_type_t type)
{
for (int idx = 0; idx < ITEMS_IN_MAC_TABLE; idx++) {
if (s_mac_table[idx].type == type) {
return s_mac_table[idx].len;
}
}
return 0;
}
esp_err_t esp_iface_mac_addr_set(const uint8_t *mac, esp_mac_type_t type)
{
if (mac == NULL) {
ESP_LOGE(TAG, "mac address param is NULL");
return ESP_ERR_INVALID_ARG;
}
int idx = get_idx(type);
if (idx == -1) {
return ESP_ERR_NOT_SUPPORTED;
}
if (type == ESP_MAC_EFUSE_FACTORY || type == ESP_MAC_EFUSE_CUSTOM) {
ESP_LOGE(TAG, "EFUSE MAC can not be set using this API");
return ESP_ERR_INVALID_ARG;
}
if (type == ESP_MAC_BASE) {
if (mac[0] & 0x01) {
ESP_LOGE(TAG, "Base MAC must be a unicast MAC");
return ESP_ERR_INVALID_ARG;
}
}
memcpy(s_mac_table[idx].mac, mac, s_mac_table[idx].len);
s_mac_table[idx].state = STATE_SET;
return ESP_OK;
}
esp_err_t esp_base_mac_addr_set(const uint8_t *mac) esp_err_t esp_base_mac_addr_set(const uint8_t *mac)
{ {
if (mac == NULL) { return esp_iface_mac_addr_set(mac, ESP_MAC_BASE);
ESP_LOGE(TAG, "Base MAC address is NULL");
return ESP_ERR_INVALID_ARG;
}
if (mac[0] & 0x01) {
ESP_LOGE(TAG, "Base MAC must be a unicast MAC");
return ESP_ERR_INVALID_ARG;
}
memcpy(base_mac_addr, mac, ESP_MAC_ADDRESS_LEN);
return ESP_OK;
} }
esp_err_t esp_base_mac_addr_get(uint8_t *mac) esp_err_t esp_base_mac_addr_get(uint8_t *mac)
{ {
if (mac == NULL) { return esp_read_mac(mac, ESP_MAC_BASE);
return ESP_ERR_INVALID_ARG;
}
if (base_mac_addr[0] == 0 && memcmp(base_mac_addr, &base_mac_addr[1], ESP_MAC_ADDRESS_LEN - 1) == 0) {
ESP_LOGI(TAG, "Base MAC address is not set");
return ESP_ERR_INVALID_MAC;
}
memcpy(mac, base_mac_addr, ESP_MAC_ADDRESS_LEN);
return ESP_OK;
} }
esp_err_t esp_efuse_mac_get_custom(uint8_t *mac) esp_err_t esp_efuse_mac_get_custom(uint8_t *mac)
@@ -169,35 +256,48 @@ esp_err_t esp_derive_local_mac(uint8_t *local_mac, const uint8_t *universal_mac)
esp_err_t esp_read_mac(uint8_t *mac, esp_mac_type_t type) esp_err_t esp_read_mac(uint8_t *mac, esp_mac_type_t type)
{ {
uint8_t efuse_mac[ESP_MAC_ADDRESS_LEN];
if (mac == NULL) { if (mac == NULL) {
ESP_LOGE(TAG, "mac address param is NULL"); ESP_LOGE(TAG, "mac address param is NULL");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
#if CONFIG_IEEE802154_ENABLED int idx = get_idx(type);
if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_IEEE802154) { if (idx == -1) {
#else return ESP_ERR_NOT_SUPPORTED;
if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_ETH) {
#endif
ESP_LOGE(TAG, "mac type is incorrect");
return ESP_ERR_INVALID_ARG;
} }
// if base mac address is not set, read one from EFUSE and then write back if (get_mac_addr_from_mac_table(mac, idx, true) == ESP_OK) {
if (esp_base_mac_addr_get(efuse_mac) != ESP_OK) { return ESP_OK;
ESP_LOGI(TAG, "read default base MAC address from EFUSE"); }
esp_efuse_mac_get_default(efuse_mac); // A MAC with a specific type has not yet been set (or generated)
esp_base_mac_addr_set(efuse_mac);
// then go ahead and generate it based on the base mac
uint8_t base_mac_addr[ESP_MAC_ADDRESS_LEN];
esp_err_t err = get_mac_addr_from_mac_table(base_mac_addr, get_idx(ESP_MAC_BASE), false);
if (err) {
ESP_LOGE(TAG, "Error reading BASE MAC address");
return ESP_FAIL;
} }
err = generate_mac(mac, base_mac_addr, type);
if (err) {
ESP_LOGE(TAG, "MAC address generation error");
return err;
}
// MAC was generated. We write it into the s_mac_table
s_mac_table[idx].state = STATE_SET;
memcpy(s_mac_table[idx].mac, mac, s_mac_table[idx].len);
return err;
}
static esp_err_t generate_mac(uint8_t *mac, uint8_t *base_mac_addr, esp_mac_type_t type)
{
switch (type) { switch (type) {
case ESP_MAC_WIFI_STA: case ESP_MAC_WIFI_STA:
memcpy(mac, efuse_mac, 6); memcpy(mac, base_mac_addr, 6);
break; break;
case ESP_MAC_WIFI_SOFTAP: case ESP_MAC_WIFI_SOFTAP:
#if CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP #if CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP
memcpy(mac, efuse_mac, 6); memcpy(mac, base_mac_addr, 6);
// as a result of some esp32s2 chips burned with one MAC address by mistake, // as a result of some esp32s2 chips burned with one MAC address by mistake,
// there are some MAC address are reserved for this bug fix. // there are some MAC address are reserved for this bug fix.
// related mistake MAC address is 0x7cdfa1003000~0x7cdfa1005fff, // related mistake MAC address is 0x7cdfa1003000~0x7cdfa1005fff,
@@ -215,12 +315,12 @@ esp_err_t esp_read_mac(uint8_t *mac, esp_mac_type_t type)
mac[5] += 1; mac[5] += 1;
#endif // IDF_TARGET_ESP32S2 #endif // IDF_TARGET_ESP32S2
#else #else
esp_derive_local_mac(mac, efuse_mac); esp_derive_local_mac(mac, base_mac_addr);
#endif // CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP #endif // CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP
break; break;
case ESP_MAC_BT: case ESP_MAC_BT:
#if CONFIG_ESP_MAC_ADDR_UNIVERSE_BT #if CONFIG_ESP_MAC_ADDR_UNIVERSE_BT
memcpy(mac, efuse_mac, 6); memcpy(mac, base_mac_addr, 6);
#if !CONFIG_IDF_TARGET_ESP32H4 #if !CONFIG_IDF_TARGET_ESP32H4
// esp32h4 chips do not have wifi module, so the mac address do not need to add the BT offset // esp32h4 chips do not have wifi module, so the mac address do not need to add the BT offset
mac[5] += MAC_ADDR_UNIVERSE_BT_OFFSET; mac[5] += MAC_ADDR_UNIVERSE_BT_OFFSET;
@@ -231,22 +331,21 @@ esp_err_t esp_read_mac(uint8_t *mac, esp_mac_type_t type)
break; break;
case ESP_MAC_ETH: case ESP_MAC_ETH:
#if CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH #if CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH
memcpy(mac, efuse_mac, 6); memcpy(mac, base_mac_addr, 6);
mac[5] += 3; mac[5] += 3;
#else #else
efuse_mac[5] += 1; base_mac_addr[5] += 1;
esp_derive_local_mac(mac, efuse_mac); esp_derive_local_mac(mac, base_mac_addr);
#endif // CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH #endif // CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH
break; break;
#if CONFIG_IEEE802154_ENABLED #if CONFIG_IEEE802154_ENABLED
case ESP_MAC_IEEE802154: case ESP_MAC_IEEE802154:
memcpy(mac, efuse_mac, 8); memcpy(mac, base_mac_addr, 8);
break; break;
#endif #endif
default: default:
ESP_LOGE(TAG, "unsupported mac type"); ESP_LOGE(TAG, "unsupported mac type");
break; return ESP_ERR_NOT_SUPPORTED;
} }
return ESP_OK; return ESP_OK;
} }

View File

@@ -19,11 +19,13 @@ choice ESP32_UNIVERSAL_MAC_ADDRESSES
config ESP32_UNIVERSAL_MAC_ADDRESSES_TWO config ESP32_UNIVERSAL_MAC_ADDRESSES_TWO
bool "Two" bool "Two"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT
config ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR config ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR
bool "Four" bool "Four"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT

View File

@@ -26,11 +26,13 @@ choice ESP32C2_UNIVERSAL_MAC_ADDRESSES
config ESP32C2_UNIVERSAL_MAC_ADDRESSES_TWO config ESP32C2_UNIVERSAL_MAC_ADDRESSES_TWO
bool "Two" bool "Two"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT
config ESP32C2_UNIVERSAL_MAC_ADDRESSES_FOUR config ESP32C2_UNIVERSAL_MAC_ADDRESSES_FOUR
bool "Four" bool "Four"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT

View File

@@ -26,11 +26,13 @@ choice ESP32C3_UNIVERSAL_MAC_ADDRESSES
config ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO config ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO
bool "Two" bool "Two"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT
config ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR config ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR
bool "Four" bool "Four"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT

View File

@@ -26,11 +26,14 @@ choice ESP32C6_UNIVERSAL_MAC_ADDRESSES
config ESP32C6_UNIVERSAL_MAC_ADDRESSES_TWO config ESP32C6_UNIVERSAL_MAC_ADDRESSES_TWO
bool "Two" bool "Two"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT
config ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR config ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR
bool "Four" bool "Four"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
select ESP_MAC_ADDR_UNIVERSE_IEEE802154
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT

View File

@@ -9,6 +9,7 @@ choice ESP32H4_UNIVERSAL_MAC_ADDRESSES
config ESP32H4_UNIVERSAL_MAC_ADDRESSES_TWO config ESP32H4_UNIVERSAL_MAC_ADDRESSES_TWO
bool "Two" bool "Two"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
select ESP_MAC_ADDR_UNIVERSE_IEEE802154 select ESP_MAC_ADDR_UNIVERSE_IEEE802154
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT
endchoice endchoice

View File

@@ -17,9 +17,12 @@ choice ESP32S2_UNIVERSAL_MAC_ADDRESSES
config ESP32S2_UNIVERSAL_MAC_ADDRESSES_ONE config ESP32S2_UNIVERSAL_MAC_ADDRESSES_ONE
bool "One" bool "One"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_ONE
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
config ESP32S2_UNIVERSAL_MAC_ADDRESSES_TWO config ESP32S2_UNIVERSAL_MAC_ADDRESSES_TWO
bool "Two" bool "Two"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
endchoice endchoice

View File

@@ -19,10 +19,13 @@ choice ESP32S3_UNIVERSAL_MAC_ADDRESSES
config ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO config ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO
bool "Two" bool "Two"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT
config ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR config ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR
bool "Four" bool "Four"
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
select ESP_MAC_ADDR_UNIVERSE_BT select ESP_MAC_ADDR_UNIVERSE_BT

View File

@@ -91,10 +91,15 @@ In ESP-IDF, the MAC addresses for the various network interfaces are calculated
.. note:: Although {IDF_TARGET_NAME} has no integrated Ethernet MAC, it is still possible to calculate an Ethernet MAC address. However, this MAC address can only be used with an external ethernet interface such as an SPI-Ethernet device. See :doc:`/api-reference/network/esp_eth`. .. note:: Although {IDF_TARGET_NAME} has no integrated Ethernet MAC, it is still possible to calculate an Ethernet MAC address. However, this MAC address can only be used with an external ethernet interface such as an SPI-Ethernet device. See :doc:`/api-reference/network/esp_eth`.
Custom Interface MAC
^^^^^^^^^^^^^^^^^^^^
Sometimes you may need to define custom MAC addresses that are not generated from the base MAC address. To set a custom interface MAC address, use the :cpp:func:`esp_iface_mac_addr_set` function. This function allows you to overwrite the MAC addresses of interfaces set (or not yet set) by the base MAC address. Once a MAC address has been set for a particular interface, changing the base MAC address does not affect it.
Custom Base MAC Custom Base MAC
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
The default base MAC is pre-programmed by Espressif in eFuse {IDF_TARGET_BASE_MAC_BLOCK}. To set a custom base MAC instead, call the function :cpp:func:`esp_base_mac_addr_set` before initializing any network interfaces or calling the :cpp:func:`esp_read_mac` function. The custom MAC address can be stored in any supported storage device (e.g., flash, NVS). The default base MAC is pre-programmed by Espressif in eFuse {IDF_TARGET_BASE_MAC_BLOCK}. To set a custom base MAC instead, call the function :cpp:func:`esp_iface_mac_addr_set` with the ``ESP_MAC_BASE`` argument (or :cpp:func:`esp_base_mac_addr_set`) before initializing any network interfaces or calling the :cpp:func:`esp_read_mac` function. The custom MAC address can be stored in any supported storage device (e.g., flash, NVS).
The custom base MAC addresses should be allocated such that derived MAC addresses will not overlap. Based on the table above, users can configure the option :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` to set the number of valid universal MAC addresses that can be derived from the custom base MAC. The custom base MAC addresses should be allocated such that derived MAC addresses will not overlap. Based on the table above, users can configure the option :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` to set the number of valid universal MAC addresses that can be derived from the custom base MAC.
@@ -106,7 +111,7 @@ The custom base MAC addresses should be allocated such that derived MAC addresse
Custom MAC Address in eFuse Custom MAC Address in eFuse
@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@
When reading custom MAC addresses from eFuse, ESP-IDF provides a helper function :cpp:func:`esp_efuse_mac_get_custom`. This loads the MAC address from eFuse BLK3. This function assumes that the custom base MAC address is stored in the following format: When reading custom MAC addresses from eFuse, ESP-IDF provides a helper function :cpp:func:`esp_efuse_mac_get_custom` or use :cpp:func:`esp_read_mac` with the ``ESP_MAC_EFUSE_CUSTOM`` argument. This loads the MAC address from eFuse BLK3. The :cpp:func:`esp_efuse_mac_get_custom` function assumes that the custom base MAC address is stored in the following format:
.. only:: esp32 .. only:: esp32
@@ -156,7 +161,10 @@ When reading custom MAC addresses from eFuse, ESP-IDF provides a helper function
The eFuse BLK3 uses RS-coding during a burn operation, which means that all eFuse fields in this block must be burnt at the same time. The eFuse BLK3 uses RS-coding during a burn operation, which means that all eFuse fields in this block must be burnt at the same time.
Once MAC address has been obtained using :cpp:func:`esp_efuse_mac_get_custom`, call :cpp:func:`esp_base_mac_addr_set` to set this MAC address as base MAC address. Once custom efuse MAC address has been obtained (using cpp:func:`esp_efuse_mac_get_custom` or :cpp:func:`esp_read_mac`) you need to set it as the base MAC address. There is two ways to do it:
1. using an old API, call :cpp:func:`esp_base_mac_addr_set`.
2. using a new API, call :cpp:func:`esp_iface_mac_addr_set` with the ``ESP_MAC_BASE`` argument.
.. _local-mac-addresses: .. _local-mac-addresses:

View File

@@ -39,7 +39,7 @@ void app_main(void)
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
#ifdef CONFIG_BASE_MAC_STORED_EFUSE_BLK3 #ifdef CONFIG_BASE_MAC_STORED_EFUSE_BLK3
//Get base MAC address from EFUSE BLK3 //Get base MAC address from EFUSE BLK3
ret = esp_efuse_mac_get_custom(base_mac_addr); ret = esp_read_mac(base_mac_addr, ESP_MAC_EFUSE_CUSTOM);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get base MAC address from EFUSE BLK3. (%s)", esp_err_to_name(ret)); ESP_LOGE(TAG, "Failed to get base MAC address from EFUSE BLK3. (%s)", esp_err_to_name(ret));
#ifdef CONFIG_BASE_MAC_STORED_EFUSE_BLK3_ERROR_ABORT #ifdef CONFIG_BASE_MAC_STORED_EFUSE_BLK3_ERROR_ABORT
@@ -47,7 +47,7 @@ void app_main(void)
abort(); abort();
#else #else
ESP_LOGI(TAG, "Defaulting to base MAC address in BLK0 of EFUSE"); ESP_LOGI(TAG, "Defaulting to base MAC address in BLK0 of EFUSE");
esp_efuse_mac_get_default(base_mac_addr); ESP_ERROR_CHECK(esp_read_mac(base_mac_addr, ESP_MAC_EFUSE_FACTORY));
ESP_LOGI(TAG, "Base MAC Address read from EFUSE BLK0"); ESP_LOGI(TAG, "Base MAC Address read from EFUSE BLK0");
#endif//CONFIG_BASE_MAC_STORED_EFUSE_BLK3_ERROR_ABORT #endif//CONFIG_BASE_MAC_STORED_EFUSE_BLK3_ERROR_ABORT
} else { } else {
@@ -65,7 +65,7 @@ void app_main(void)
} }
#else #else
//Get base MAC address from EFUSE BLK0(default option) //Get base MAC address from EFUSE BLK0(default option)
ret = esp_efuse_mac_get_default(base_mac_addr); ret = esp_read_mac(base_mac_addr, ESP_MAC_EFUSE_FACTORY);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get base MAC address from EFUSE BLK0. (%s)", esp_err_to_name(ret)); ESP_LOGE(TAG, "Failed to get base MAC address from EFUSE BLK0. (%s)", esp_err_to_name(ret));
ESP_LOGE(TAG, "Aborting"); ESP_LOGE(TAG, "Aborting");
@@ -78,10 +78,12 @@ void app_main(void)
//Set the base MAC address using the retrieved MAC address //Set the base MAC address using the retrieved MAC address
ESP_LOGI(TAG, "Using \"0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\" as base MAC address", ESP_LOGI(TAG, "Using \"0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\" as base MAC address",
base_mac_addr[0], base_mac_addr[1], base_mac_addr[2], base_mac_addr[3], base_mac_addr[4], base_mac_addr[5]); base_mac_addr[0], base_mac_addr[1], base_mac_addr[2], base_mac_addr[3], base_mac_addr[4], base_mac_addr[5]);
esp_base_mac_addr_set(base_mac_addr); esp_iface_mac_addr_set(base_mac_addr, ESP_MAC_BASE);
//Get the derived MAC address for each network interface //Get the derived MAC address for each network interface
uint8_t derived_mac_addr[6] = {0}; uint8_t derived_mac_addr[6] = {0};
#ifdef CONFIG_ESP32_WIFI_ENABLED
//Get MAC address for WiFi Station interface //Get MAC address for WiFi Station interface
ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_WIFI_STA)); ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_WIFI_STA));
ESP_LOGI("WIFI_STA MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ESP_LOGI("WIFI_STA MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
@@ -93,18 +95,28 @@ void app_main(void)
ESP_LOGI("SoftAP MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ESP_LOGI("SoftAP MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2], derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2],
derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]); derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]);
#endif // CONFIG_ESP32_WIFI_ENABLED
#if CONFIG_ESP_MAC_ADDR_UNIVERSE_BT #ifdef CONFIG_ESP_MAC_ADDR_UNIVERSE_BT
//Get MAC address for Bluetooth //Get MAC address for Bluetooth
ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_BT)); ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_BT));
ESP_LOGI("BT MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ESP_LOGI("BT MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2], derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2],
derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]); derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]);
#endif //SOC_BT_SUPPORTED #endif // CONFIG_ESP_MAC_ADDR_UNIVERSE_BT
//Get MAC address for Ethernet //Get MAC address for Ethernet
ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_ETH)); ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_ETH));
ESP_LOGI("Ethernet MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ESP_LOGI("Ethernet MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2], derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2],
derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]); derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]);
ESP_LOGI("Ethernet MAC", "Overwrite Ethernet MAC");
base_mac_addr[5] += 6;
ESP_ERROR_CHECK(esp_iface_mac_addr_set(base_mac_addr, ESP_MAC_ETH));
ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_ETH));
ESP_LOGI("New Ethernet MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2],
derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]);
} }

View File

@@ -33,9 +33,14 @@ def test_base_mac_address(dut: Dut) -> None:
return ', '.join(['0x{}'.format(m.decode('utf8')) for m in mac_m[:-1]] + [hex(int(mac_m[-1], 16) + increment)]) return ', '.join(['0x{}'.format(m.decode('utf8')) for m in mac_m[:-1]] + [hex(int(mac_m[-1], 16) + increment)])
dut.expect_exact('WIFI_STA MAC: ' + get_expected_mac_string(0, dut.target), timeout=2) sdkconfig = dut.app.sdkconfig
dut.expect_exact('SoftAP MAC: ' + get_expected_mac_string(1, dut.target))
if sdkconfig.get('ESP32_WIFI_ENABLED'):
dut.expect_exact('WIFI_STA MAC: ' + get_expected_mac_string(0, dut.target), timeout=2)
dut.expect_exact('SoftAP MAC: ' + get_expected_mac_string(1, dut.target))
if dut.target != 'esp32s2': if dut.target != 'esp32s2':
dut.expect_exact('BT MAC: ' + get_expected_mac_string(2, dut.target)) if sdkconfig.get('ESP_MAC_ADDR_UNIVERSE_BT'):
dut.expect_exact('BT MAC: ' + get_expected_mac_string(2, dut.target))
dut.expect_exact('Ethernet MAC: ' + get_expected_mac_string(3, dut.target)) dut.expect_exact('Ethernet MAC: ' + get_expected_mac_string(3, dut.target))
dut.expect_exact('New Ethernet MAC: ' + get_expected_mac_string(6, dut.target))