diff --git a/components/esp_hw_support/include/esp_mac.h b/components/esp_hw_support/include/esp_mac.h index 0087c9a884..698ccaa6e2 100644 --- a/components/esp_hw_support/include/esp_mac.h +++ b/components/esp_hw_support/include/esp_mac.h @@ -47,17 +47,17 @@ typedef enum { * @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 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. + * Base MAC address is used to generate the MAC addresses used by network interfaces. + * + * If using a custom base MAC address, call this API before initializing any network interfaces. + * Refer to the ESP-IDF Programming Guide for details about how the Base MAC is used. * * @note Base MAC must be a unicast MAC (least significant bit of first byte must be zero). * * @note If not using a valid OUI, set the "locally administered" bit * (bit value 0x02 in the first byte) to avoid collisions. * - * @param mac base MAC address, length: 6 bytes. + * @param mac base MAC address, length: 6 bytes. * * @return ESP_OK on success * ESP_ERR_INVALID_ARG If mac is NULL or is not a unicast MAC @@ -67,7 +67,9 @@ esp_err_t esp_base_mac_addr_set(const uint8_t *mac); /** * @brief Return base MAC address which is set using esp_base_mac_addr_set. * - * @param mac base MAC address, length: 6 bytes. + * @note If no custom Base MAC has been set, this returns the pre-programmed Espressif base MAC address. + * + * @param mac base MAC address, length: 6 bytes. * * @return ESP_OK on success * ESP_ERR_INVALID_MAC base MAC address has not been set @@ -78,10 +80,14 @@ 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. - * This API returns the custom base MAC address which was previously written to BLK3 of EFUSE. + * This API returns the custom base MAC address which was previously written to EFUSE BLK3 in + * a specified format. + * * 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. * + * @note This function is currently only supported on ESP32. + * * @param mac base MAC address, length: 6 bytes. * * @return ESP_OK on success @@ -91,7 +97,7 @@ esp_err_t esp_base_mac_addr_get(uint8_t *mac); 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. + * @brief Return base MAC address which is factory-programmed by Espressif in EFUSE. * * @param mac base MAC address, length: 6 bytes. * @@ -102,12 +108,12 @@ esp_err_t esp_efuse_mac_get_default(uint8_t *mac); /** * @brief Read base MAC address and set MAC address of the interface. * - * 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. + * This function first get base MAC address using esp_base_mac_addr_get(). + * Then calculates the MAC address of the specific interface requested, + * refer to ESP-IDF Programming Guide for the algorithm. * * @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. + * @param type Type of MAC address to return * * @return ESP_OK on success */ @@ -116,12 +122,13 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type); /** * @brief Derive local MAC address from universal MAC address. * - * This function copies a universal MAC address and then sets the U/L bit - * (bit 0x2) in the first octet, creating a locally administered MAC address. + * This function copies a universal MAC address and then sets the "locally + * administered" bit (bit 0x2) in the first octet, creating a locally + * administered MAC address. * - * It's not recommended that the universal MAC address argument is already a - * locally administered MAC address, but in this case the first octet is XORed - * with 0x4 in order to create a different locally administered MAC address. + * If the universal MAC address argument is already a locally administered MAC + * address, then the first octet is XORed with 0x4 in order to create a different + * locally administered MAC address. * * @param local_mac Derived local MAC address, length: 6 bytes. * @param universal_mac Source universal MAC address, length: 6 bytes. diff --git a/components/esp_hw_support/port/esp32c3/Kconfig.mac b/components/esp_hw_support/port/esp32c3/Kconfig.mac index ef3224b97d..ea53535782 100644 --- a/components/esp_hw_support/port/esp32c3/Kconfig.mac +++ b/components/esp_hw_support/port/esp32c3/Kconfig.mac @@ -3,20 +3,27 @@ choice ESP32C3_UNIVERSAL_MAC_ADDRESSES default ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR help Configure the number of universally administered (by IEEE) MAC addresses. + During initialization, 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.) + Note that ESP32-C3 has no integrated Ethernet MAC. Although it's possible to use the esp_read_mac() + API to return a MAC for Ethernet, this can only be used with an external MAC peripheral. + config ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO bool "Two" select ESP_MAC_ADDR_UNIVERSE_WIFI_STA diff --git a/docs/en/api-reference/system/system.rst b/docs/en/api-reference/system/system.rst index cc4b5f713a..5038f99dd5 100644 --- a/docs/en/api-reference/system/system.rst +++ b/docs/en/api-reference/system/system.rst @@ -1,6 +1,8 @@ Miscellaneous System APIs ========================= +{IDF_TARGET_BASE_MAC_BLOCK: default="BLK1", esp32="BLK0"} + Software reset -------------- @@ -37,94 +39,113 @@ MAC Address These APIs allow querying and customizing MAC addresses for different network interfaces that supported (e.g. Wi-Fi, Bluetooth, Ethernet). -In ESP-IDF these addresses are calculated from *Base MAC address*. Base MAC address can be initialized with factory-programmed value from internal eFuse, or with a user-defined value. In addition to setting the base MAC address, applications can specify the way in which MAC addresses are allocated to devices. See `Number of universally administered MAC address`_ section for more details. +.. only:: SOC_BT_SUPPORTED -.. only:: esp32 and esp32c3 + To fetch MAC address for a specific interface (e.g. Wi-Fi, Bluetooth, Ethernet), call the function :cpp:func:`esp_read_mac` function. - +---------------+--------------------------------+----------------------------------+ - | Interface | MAC address | MAC address | - | | (4 universally administered) | (2 universally administered) | - +===============+================================+==================================+ - | Wi-Fi Station | base_mac | base_mac | - +---------------+--------------------------------+----------------------------------+ - | Wi-Fi SoftAP | base_mac, +1 to the last octet | base_mac, first octet randomized | - +---------------+--------------------------------+----------------------------------+ - | Bluetooth | base_mac, +2 to the last octet | base_mac, +1 to the last octet | - +---------------+--------------------------------+----------------------------------+ - | Ethernet | base_mac, +3 to the last octet | base_mac, +1 to the last octet, | - | | | first octet randomized | - +---------------+--------------------------------+----------------------------------+ +.. only:: not SOC_BT_SUPPORTED + + To fetch MAC address for a specific interface (e.g. Wi-Fi Station, Wi-Fi SoftAP), call the function :cpp:func:`esp_read_mac` function. + +In ESP-IDF these addresses are calculated from a single *Base MAC address*. By default, the Espressif base MAC address is used. This MAC is pre-programmed into {IDF_TARGET_NAME} eFuse from the factory. + +.. only:: not esp32s2 + + +---------------+---------------------------------------+-----------------------------------------------+ + | Interface | MAC address | MAC address | + | | (4 universally administered, default) | (2 universally administered) | + +===============+=======================================+===============================================+ + | Wi-Fi Station | base_mac | base_mac | + +---------------+---------------------------------------+-----------------------------------------------+ + | Wi-Fi SoftAP | base_mac, +1 to the last octet | :ref:`Local MAC ` | + | | | derived from Wi-Fi Station MAC) | + +---------------+---------------------------------------+-----------------------------------------------+ + | Bluetooth | base_mac, +2 to the last octet | base_mac, +1 to the last octet | + +---------------+---------------------------------------+-----------------------------------------------+ + | Ethernet | base_mac, +3 to the last octet | :ref:`Local MAC ` | + | | | (derived from Bluetooth MAC) | + +---------------+---------------------------------------+-----------------------------------------------+ + + .. note:: + + The default :ref:`configuration ` + is 4 universally administered MAC addresses, and this is recommended when using + Espressif-provided MAC addresses. .. only:: esp32s2 - +---------------+--------------------------------+----------------------------------+ - | Interface | MAC address | MAC address | - | | (2 universally administered) | (1 universally administered) | - +===============+================================+==================================+ - | Wi-Fi Station | base_mac | base_mac | - +---------------+--------------------------------+----------------------------------+ - | Wi-Fi SoftAP | base_mac, +1 to the last octet | base_mac, first octet randomized | - +---------------+--------------------------------+----------------------------------+ + +---------------+---------------------------------------+-----------------------------------------------+ + | Interface | MAC address | MAC address | + | | (2 universally administered, default) | (1 universally administered) | + +===============+=======================================+===============================================+ + | Wi-Fi Station | base_mac | base_mac | + +---------------+---------------------------------------+-----------------------------------------------+ + | Wi-Fi SoftAP | base_mac, +1 to the last octet | :ref:`Local MAC ` | + | | | (derived from Wi-Fi Station MAC) | + +---------------+---------------------------------------+-----------------------------------------------+ + | Ethernet | :ref:`Local MAC `| :ref:`Local MAC ` | + | (see note) | (derived from Wi-Fi SoftAP MAC | (derived from base_mac with +1 to last octet. | + | | | Not recommended.) | + +---------------+---------------------------------------+-----------------------------------------------+ -Base MAC address -^^^^^^^^^^^^^^^^ + .. note:: -To fetch MAC address for a specific interface (e.g. Wi-Fi, Bluetooth, Ethernet), you can simply use :cpp:func:`esp_read_mac` function. + The default :ref:`configuration ` + is 2 universally administered MAC addresses, and this is recommended when using + Espressif-provided MAC addresses. -By default, this function takes the eFuse value burned at a pre-defined block (e.g. BLK0 for ESP32, BLK1 for ESP32-S2) as the base MAC address. Per-interface MAC addresses will be calculated according to the table above. +.. only:: not SOC_EMAC_SUPPORTED -Applications who want to customize base MAC address (not the one provided by Espressif) should call :cpp:func:`esp_base_mac_addr_set` before :cpp:func:`esp_read_mac`. The customized MAC address can be stored in any supported storage device (e.g. Flash, NVS, etc). + .. note:: {IDF_TARGET_NAME} has no integrated Ethernet MAC, but it's still possible to calculate an Ethernet MAC address. This MAC address can only be used with an external interface such as a SPI-Ethernet device, see :doc:`/api-reference/network/esp_eth`. -Note that, calls to :cpp:func:`esp_base_mac_addr_set` should take place before the initialization of network stack, for example, early in ``app_main``. +Custom Base MAC +^^^^^^^^^^^^^^^ -Custom MAC address in eFuse -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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 customized MAC address can be stored in any supported storage device (e.g. Flash, NVS, etc). -To facilitate the usage of custom MAC addresses, ESP-IDF provides :cpp:func:`esp_efuse_mac_get_custom` function, which loads MAC address from internal pre-defined eFuse block (e.g. BLK3 for ESP32). This function assumes that custom MAC address is stored in the following format: +The custom base MAC addresses should be allocated such that derived MAC addresses will not overlap. 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, according to the table above. -+-----------------+-----------+---------------+------------------------------+ -| Field | # of bits | Range of bits | Notes | -+=================+===========+===============+==============================+ -| Version | 8 | 191:184 | 0: invalid, others — valid | -+-----------------+-----------+---------------+------------------------------+ -| Reserved | 128 | 183:56 | | -+-----------------+-----------+---------------+------------------------------+ -| MAC address | 48 | 55:8 | | -+-----------------+-----------+---------------+------------------------------+ -| MAC address CRC | 8 | 7:0 | CRC-8-CCITT, polynomial 0x07 | -+-----------------+-----------+---------------+------------------------------+ +.. note:: -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. + It is also possible to call the function :cpp:func:`esp_netif_set_mac` to set the specific MAC used by a network interface, after network initialization. It's recommended to use the Base MAC approach documented here instead, to avoid the possibility of the original MAC address briefly appearing on the network before it is changed. +.. This API is ESP32-only, see IDF-1326 +.. only:: esp32 -Number of universally administered MAC address -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Custom MAC address in eFuse + @@@@@@@@@@@@@@@@@@@@@@@@@@@ -Several MAC addresses (universally administered by IEEE) are uniquely assigned to the networking interfaces (Wi-Fi/BT/Ethernet). The final octet of each universally administered MAC address increases by one. Only the first one of them (which is called base MAC address) 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. + 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: -If the universally administered MAC addresses are not enough for all of the networking interfaces, locally administered MAC addresses which are derived from universally administered MAC addresses are assigned to the rest of networking interfaces. + +-----------------+-----------+---------------+------------------------------+ + | Field | # of bits | Range of bits | Notes | + +=================+===========+===============+==============================+ + | Version | 8 | 191:184 | 0: invalid, others — valid | + +-----------------+-----------+---------------+------------------------------+ + | Reserved | 128 | 183:56 | | + +-----------------+-----------+---------------+------------------------------+ + | MAC address | 48 | 55:8 | | + +-----------------+-----------+---------------+------------------------------+ + | MAC address CRC | 8 | 7:0 | CRC-8-CCITT, polynomial 0x07 | + +-----------------+-----------+---------------+------------------------------+ -See `this article `_ for the definition of local and universally administered MAC addresses. + 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. -.. only:: esp32 and esp32c3 +.. _local-mac-addresses: - The number of universally administered MAC address can be configured using :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES`. +Local vs Universal MAC addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - If the number of universal MAC addresses is two, only two interfaces (Wi-Fi 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 (Wi-Fi SoftAP and Ethernet) receive local MAC addresses. These are derived from the universal Wi-Fi station and Bluetooth MAC addresses, respectively. +{IDF_TARGET_NAME} comes pre-programmed with enough valid Espressif universally administered MAC addresses for all internal interfaces. The specific calculations to derive an interface's MAC address from the base MAC address is shown in the table above.. - If the number of universal MAC addresses is four, all four interfaces (Wi-Fi Station, Wi-Fi 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 a custom MAC address scheme, it's possible that not all interfaces can be assigned a universally administered MAC address. In these cases, a locally administered MAC address is assigned. Note that these addresses are intended for use on a single local network, only. - 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.) +See `this article `_ for the definition of local and universally administered MAC addresses. -.. only:: esp32s2 +Function :cpp:func:`esp_derive_local_mac` is called internally to derive a local MAC address from a universal MAC address. The process is as follows: - The number of universally administered MAC address can be configured using :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES`. - - If the number of universal MAC addresses is one, only one interface (Wi-Fi Station) receive a universally administered MAC address. This is generated by adding 0 to the base MAC address. The remaining interface (Wi-Fi SoftAP) receive a local MAC address. This is derived from the universal Wi-Fi station. - - If the number of universal MAC addresses is two, both interfaces (Wi-Fi Station, Wi-Fi SoftAP) receive a universally administered MAC address. These are generated sequentially by adding 0 and 1 (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 1 or 2 per device.) +1. The U/L bit (bit value 0x2) is set in the first octet of the universal MAC address, creating a local MAC address. +2. If this bit is already set in the supplied universal MAC address (meaning: the supplied "universal" MAC address was in fact already a local MAC address), then the first octet of the local MAC address is XORed with 0x4. Chip version ------------