[Software Reset]
Для выполнения программного сброса (software reset) предоставляется функция esp_restart(). Когда эта функция вызвана, выполнение программы останавливается, CPU сбрасывается, и приложение загружается кодом bootloader, после чего приложение снова запускается.
Дополнительно может быть зарегистрирована функция esp_register_shutdown_handler() как подпрограмма, которая будет автоматически вызвана перед перезапуском (который был из-за esp_restart()). Функционал этого аналогичен функции atexit POSIX.
[Reset Reason]
Приложение ESP-IDF может быть запущено или сброшено по разным причинам - после перепрошивки, из-за сбоя программного обеспечения, из-за пропадания питания. Чтобы узнать последнюю причину, которая вызвала перезагрузку (reset reason), вызовите функцию esp_reset_reason(). В перечислении esp_reset_reason_t определен список возможных причин сброса.
/**
* @brief Причины сброса
*/
typedef enum
{
ESP_RST_UNKNOWN, //!< Причину сброса выяснить не удалось
ESP_RST_POWERON, //!< Сброс после подачи питания (power-on event)
ESP_RST_EXT, //!< Сброс от внешнего вывода (неприменимо для ESP32)
ESP_RST_SW, //!< Программный сброс от вызова esp_restart
ESP_RST_PANIC, //!< Программный сброс из-за сбоя ПО (exception/panic)
ESP_RST_INT_WDT, //!< Сброс (программный или аппаратный) из-за прерывания
// от сторожевого таймера (interrupt watchdog)
ESP_RST_TASK_WDT, //!< Сброс из-за задачи сторожевого таймера (task watchdog)
ESP_RST_WDT, //!< Сброс из-за других сторожевых таймеров
ESP_RST_DEEPSLEEP, //!< Сброс после выхода из режима deep sleep
ESP_RST_BROWNOUT, //!< Сброс от сбоя по питанию (brownout reset,
// программный или аппаратный)
ESP_RST_SDIO, //!< Сброс через SDIO
} esp_reset_reason_t;
[Память кучи]
Предоставляются 2 функции, связанные с кучей (heap):
esp_get_free_heap_size() возвратит текущий размер свободной памяти в куче.
esp_get_minimum_free_heap_size() возвратит минимальный размер свободной памяти кучи, который был когда-либо доступен (т. е. самый маленький размер свободной памяти в куче, который был за время жизни приложения).
Обратите внимание, что ESP-IDF поддерживает несколько куч с разными возможностями. Функции, упомянутые в этой секции, возвратят размер памяти кучи, которую можно выделить с использованием функций семейства malloc. Для дополнительной информации о памяти кучи см. [2].
[MAC-адрес]
Эти функции позволяют запрашивать и настраивать MAC-адреса различных сетевых интерфейсов (например Wi-Fi, Bluetooth, Ethernet).
Для извлечения MAC-адреса определенного сетевого интерфейса (Wi-Fi, Bluetooth, Ethernet) вызовите функцию esp_read_mac().
В ESP-IDF адреса MAC для различных сетевых интерфейсов вычисляются из одного базового MAC-адреса. По умолчанию используется Espressif base MAC. Этот базовый MAC-адрес предварительно программируется в eFuse-память ESP32-C3 на заводе, в процессе производства чипов.
Таблица 1. Принцип назначения MAC-адресов для различных интерфейсов.
Интерфейс |
MAC-адрес (4 универсально администрируемых, по умолчанию) |
MAC-адрес (2 универсально администрируемых) |
Wi-Fi Station |
base_mac |
base_mac |
Wi-Fi SoftAP |
base_mac, +1 к последнему октету |
Local MAC (вычисляется из Wi-Fi Station MAC) |
Bluetooth |
base_mac, +2 к последнему октету |
base_mac, +1 к последнему октету |
Ethernet |
base_mac, +3 к последнему октету |
Local MAC (вычисляется из Bluetooth MAC) |
Конфигурация задает количество универсально администрируемых MAC-адресов, которые предоставлены Espressif.
Примечание: хотя у ESP32-C3 нет встроенной аппаратуры Ethernet MAC, все еще можно вычислить адрес Ethernet MAC. Однако этот MAC-адрес может использоваться только с внешним интерфейсом Ethernet, таким как устройство SPI-Ethernet [3].
Custom Interface MAC. Иногда может понадобиться определить пользовательский MAC-адрес, который не был сгенерирован на основе base MAC address. Чтобы установить MAC-адрес пользовательского интерфейса, используйте функцию esp_iface_mac_addr_set(). Она позволяет перезаписать MAC-адреса для набора интерфейсов. Как только MAC-адрес для определенного интерфейса был установлен, на него больше не будет влиять изменение базового MAC-адреса.
Custom Base MAC. Базовый MAC по умолчанию запрограммирован на заводе Espressif в eFuse BLK1. Чтобы установить вместо него пользовательский базовый MAC, вызовите функцию esp_iface_mac_addr_set() с аргументом ESP_MAC_BASE (или esp_base_mac_addr_set()) перед инициализацией любого сетевого интерфейса или вызова esp_read_mac(). Пользовательский MAC-адрес может быть сохранен в любое поддерживаемое энергонезависимое хранилище (например flash, NVS).
Адреса custom base MAC должны быть выделены таким образом, чтобы вычисленные MAC-адреса не перекрывались. На основе показанной выше таблицы 1 пользователи могут сконфигурировать опцию CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES для установки количества допустимых универсальных MAC-адресов, которые могут быть вычислены из custom base MAC.
Примечание: можно вызвать esp_netif_set_mac() для установки определенного MAC, используемого сетевым интерфейсом, после инициализации сети. Однако рекомендуется использовать базовый подход к MAC-адресам, описанный здесь, чтобы избежать возможности краткого отображения исходного MAC-адреса в сети перед его изменением.
Custom MAC Address в eFuse. Когда из eFuse считываются пользовательские MAC-адреса, ESP-IDF предоставляет вспомогательную функцию esp_mac_get_custom(). Пользователи могут также использовать для этого esp_read_mac() с параметром ESP_MAC_EFUSE_CUSTOM. Это загрузит MAC-адрес из eFuse BLK3. Функция esp_mac_get_custom() подразумевает, что custom base MAC address сохранен в следующем формате:
Поле |
Количество бит |
Диапазон бит eFuse |
MAC-адрес |
48 |
200:248 |
Примечание: eFuse BLK3 при прошивке значений бит использует RS-кодирование. Это означает, что все поля eFuse в этом блоке должны быть прошиты одновременно.
Как только custom eFuse MAC address был получен (с использованием esp_efuse_mac_get_custom() или esp_read_mac()), вам нужно установить его как base MAC address. Для этого существует 2 способа:
Старое API: вызов esp_base_mac_addr_set(). Новое API: вызов esp_iface_mac_addr_set() с аргументом ESP_MAC_BASE.
Local MAC против Universal MAC. ESP32-C3 поставляется запрограммированным достаточным количеством универсально администрируемых MAC-адресов Espressif для всех внутренних интерфейсов. В таблице 1 показано, как вычислить и получить MAC-адрес для определенного интерфейса в соответствии с base MAC address.
Когда используется пользовательская схема MAC-адресов (custom MAC address), возможна ситуация, когда не всем интерфейсам может быть назначен универсально администрируемый MAC-адрес (Universal MAC). В таких случаях назначается локально администрируемый MAC-адрес (Local MAC). Обратите внимание, что эти адреса предназначены только для использования в одной локальной сети. См. Википедию [4] для определения локально и универсально администрируемых MAC-адресов.
Функция esp_derive_local_mac() вызывается внутри системы для получения локального MAC-адреса из универсального MAC-адреса. Этот процесс заключается в следующем:
1. Бит U/L (значение бита 0x2) устанавливается в первом октете универсального MAC-адреса, создавая локальный MAC-адрес.
2. Если этот бит уже установлен в предоставленном универсальном MAC-адресе (например предоставленный "универсальный" MAC-адрес уже был фактически локальным MAC-адресом), то на первый октет локального MAC-адреса применяется операция XOR со значением 0x4.
[Chip Version]
Функция esp_chip_info() заполнит структуру esp_chip_info_t информацией работающего чипа. Она включает ревизию чипа, количество ядер CPU и битовую маску функций, разрешенных в чипе.
[SDK Version]
Функция esp_get_idf_version() возвратит строку, описывающую версию ESP-IDF, которая использовалась для компиляции приложения. У этой строки такое же значение, которое доступна в переменной IDF_VER системы сборки [6]. У строки версии обычно такой же формат, как у вывода команды git describe.
Чтобы получить значение версии во время сборки, предоставляются дополнительные макросы. Они могут использоваться для разрешения или запрета определенных частей программы в зависимости от версии ESP-IDF version.
ESP_IDF_VERSION_MAJOR, ESP_IDF_VERSION_MINOR, ESP_IDF_VERSION_PATCH определены в целые числа, представляющие значения версий major, minor и patch.
ESP_IDF_VERSION_VAL и ESP_IDF_VERSION могут использоваться для реализации проверок версии:
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
// Разрешен функционал, присутствующий в ESP-IDF v4.0
#endif
[App Version]
Версия приложения сохранена в структуре esp_app_desc_t [7]. Она находится в секторе DROM, и имеет фиксированное смещение относительно двоичного образа файла прошивки. Эта структура находится за структурами esp_image_header_t и esp_image_segment_header_t. Тип поля version это строка с максимум 3 символами, включая байт 0 в качестве терминатора строки.
Чтобы вручную установить версию проекта, необходимо установить значение переменной PROJECT_VER в файле CMakeLists.txt проекта. В файле CMakeLists.txt приложения поместите строку set(PROJECT_VER "0.1.0.1") перед подключением project.cmake.
Если установлена опция CONFIG_APP_PROJECT_VER_FROM_CONFIG, то будет использоваться значение опции CONFIG_APP_PROJECT_VER. Иначе, если переменная PROJECT_VER в проекте не установлена, она будет получена либо из файла $(PROJECT_PATH)/version.txt (если он присутствует) либо с помощью команды git describe. Если ничего из этого недоступно, то PROJECT_VER будет установлено в "1". Приложение может использовать это значение вызовом функций esp_app_get_description() или esp_ota_get_partition_description().
[Справочник по API-функциям]
В следующей таблице приведено общее описание назначения API-функций. Полное описание параметров и возвращаемых значений функций, а также используемых для них типов, перечислений и макросов см. в документации [1].
Функция |
Описание |
Заголовочный файл: components/esp_system/include/esp_system.h |
esp_register_shutdown_handler |
Регистрирует функцию обработчика момента выключения. Эта функция позволяет вам зарегистрировать обработчик, который получает управление перед тем, как приложение будет перезагружено с использованием функции esp_restart. |
esp_unregister_shutdown_handler |
Отменяет регистрацию обработчика выключения, которая была ранее произведена вызовом esp_register_shutdown_handler. |
esp_restart |
Перезагрузит CPU-ядра PRO и APP [5]. Эта функция может быть вызвана из обоих ядер, и PRO, и APP. После успешного рестарта причина сброса (CPU reset reason) будет SW_CPU_RESET (программный сброс). Периферийные устройства (кроме Wi-Fi, BT, UART0, SPI1 и legacy-таймеры) при этом не сбрасываются. Из этой функции нет возврата. |
esp_reset_reason |
Считывает причину последнего сброса. |
esp_get_free_heap_size |
Извлекает размер доступной области кучи. Имейте в виду, что возращенное значение может быть больше, чем максимальный размер непрерывного блока памяти, который может быть выделен. |
esp_get_free_internal_heap_size |
Извлекает размер доступной внутренней кучи. Имейте в виду, что возращенное значение может быть больше, чем максимальный размер непрерывного блока памяти, который может быть выделен. |
esp_get_minimum_free_heap_size |
Извлекает минимальный размер кучи, который когда-либо был доступен за время жизни приложения. |
esp_system_abort |
Вызовет срабатывание программного abort. |
Заголовочный файл: components/esp_common/include/esp_idf_version.h |
esp_get_idf_version |
Возвратит полную строку версии IDF в таком же стиле, как и у команды git describe. Если вы в файл лога печатаете версию ESP-IDF или другую информацию, то эта функция предоставит больше информации, чем при использовании числовых макросов версии. Например, числовые макросы версии не различают версии development, pre-release и release versions, однако в выводе этой функции такая информация присутствует. |
Заголовочный файл: components/esp_hw_support/include/esp_mac.h |
esp_base_mac_addr_set |
Установит базовый MAC-адрес, который сохраняется в BLK3 EFUSE или внешнем хранилище, таком как flash и EEPROM. Базовый MAC-адрес используется для генерации MAC-адресов для сетевых интерфейсов. Если используется пользовательский базовый MAC-адрес (custom base MAC address), то вызовите эту API-функцию перед инициализацией любых сетевых интерфейсов. Подробности о том, как используется Base MAC, см. в руководстве программирования (ESP-IDF Programming Guide). Замечания: Base MAC должен быть unicast MAC (самый младший значащий бит первого байта должен быть 0). Если не используется правильный OUI (Organizationally Unique Identifier, уникальный идентификатор организации), то установите бит "locally administered" (значение бит 0x02 в первом байте), чтобы избежать коллизий. |
esp_base_mac_addr_get |
Возвратит базовый MAC-адрес, который был установлен с использованием esp_base_mac_addr_set. Если не был установлен Base MAC, то эта функция вернет предварительно запрограммированный Base MAC от Espressif. |
esp_efuse_mac_get_custom |
Вернет базовый MAC-адрес, который был ранее записан в BLK3 EFUSE. Base MAC используется для генерации MAC-адресов сетевых адаптеров. Эта API-функция вернет пользовательский базовый MAC-адрес (custom base MAC address), который был ранее записан в EFUSE BLK3 в специальном формате. Запись этих EFUSE позволяет установить другой (не-Espressif) базовый MAC-адрес. Также есть возможность сохранить пользовательский базовый MAC-адрес где-нибудь в другом месте, см. описание esp_base_mac_addr_set() для подробностей. Замечание: эта функция в настоящий момент поддерживается только микроконтроллером ESP32. |
esp_efuse_mac_get_default |
Возвратит базовый MAC-адрес, который был запрограммирован в EFUSE на заводе Espressif. |
esp_read_mac |
Прочитает базовый MAC-адрес и установит MAC-адрес интерфейса. Эта функция сначала извлечет базовый MAC-адрес вызовом esp_base_mac_addr_get(). Затем она вычислит MAC-адрес для определенного запрошенного интерфейса, описание этого алгоритма см. в руководстве по программированию (ESP-IDF Programming Guide). MAC-адрес, установленный вызовом esp_iface_mac_addr_set(), не будет зависеть от базового MAC-адреса. |
esp_derive_local_mac |
Вычисляет локальный MAC-адрес (local MAC address) из универсального (universal MAC address). Эта функция копирует универсальный MAC-адрес, и затем установит бит "locally administered" (бит 0x2) в первом байте, создавая тем самым локально администрируемый MAC-адрес. Если аргумент универсального MAC-адреса уже является локально администрируемым MAC-адресом, то на первый байт операцией XOR накладывается значение 0x4, чтобы создать другой локально администрируемый MAC-адрес. |
esp_iface_mac_addr_set |
Установит пользовательский MAC-адрес интерфейса. Эта функция позволит вам перезаписать MAC-адреса интерфейсов, задаваемые базовым MAC-адресом. |
esp_mac_addr_len_get |
Возвратит размер типа MAC в байтах. Если установлено CONFIG_IEEE802154_ENABLED, то для этих типов: ESP_MAC_IEEE802154, ESP_MAC_BASE, ESP_MAC_EFUSE_FACTORY и ESP_MAC_EFUSE_CUSTOM размер MAC составит 8 байт. Если не установлено CONFIG_IEEE802154_ENABLED, то все типы MAC-адресов имеют размер 6 байт. |
Заголовочный файл: components/esp_hw_support/include/esp_chip_info.h |
esp_chip_info |
Заполнит структуру esp_chip_info_t информацией о чипе микроконтроллера. |
Заголовочный файл: components/esp_hw_support/include/esp_cpu.h |
esp_cpu_stall |
Приостановит ядро CPU. |
esp_cpu_unstall |
Возобновит работу ранее приостановленного ядра CPU. |
esp_cpu_reset |
Сбросит ядро CPU. |
esp_cpu_wait_for_intr |
Функция выполняет блокировку в ожидании прерывания (Wait for Interrupt). Эта функция заставит текущее ядро CPU выполнить инструкцию Wait For Interrupt (WFI или эквивалентную). После выполнения этой функции ядро CPU остановит выполнение кода до момента возникновения прерывания. |
esp_cpu_get_core_id |
Извлечет идентификатор (ID) текущего ядра. Эта функция вернет ID текущего CPU (т. е. того ядра CPU, которое вызвало эту функцию). |
esp_cpu_get_sp |
Прочитает текущее значение адреса указателя стека. |
esp_cpu_get_cycle_count |
Извлечет значение счетчика тактов текущего ядра CPU. Каждое ядро CPU обслуживает отдельный внутренний счетчик (счетчик циклов), который инкрементируется с каждым тактом CPU. |
esp_cpu_set_cycle_count |
Установит внутренний счетчик тактов текущего CPU. Установит указанным значением внутренний счетчик, который инкрементируется каждый такт CPU. |
esp_cpu_pc_to_addr |
Преобразует значение счетчика программы (program counter, PC) в адрес. Если архитектура не сохраняет истинный виртуальный адрес CPU PC или адрес возврата, то эта функция преобразует значение PC в виртуальный адрес. Иначе будет просто возвращено значение PC. |
esp_cpu_intr_get_desc |
Извлечет дескриптор прерывания CPU. У каждого CPU есть дескриптор, описывающий возможности прерываний и соответствующие ограничения. Эта функция извлечет дескриптор определенного прерывания на определенном CPU. |
esp_cpu_intr_set_ivt_addr |
Установит базовый адрес таблицы векторов прерываний (Interrupt Vector Table, IVT) текущего CPU. |
esp_cpu_intr_set_type |
Установит тип определенного прерывания. Установка типа прерывания - по уровню (Level) или по перепаду (Edge) - происходит для текущего CPU. |
esp_cpu_intr_get_type |
Извлечет текущий сконфигурированный тип определенного прерывания. Извлекается сконфигурированный в настоящий момент тип (Level или Edge) определенного прерывания у текущего CPU. |
esp_cpu_intr_set_priority |
Установит приоритет у определенного прерывания текущего CPU. |
esp_cpu_intr_get_priority |
Извлечет текущий сконфигурированный приоритет у определенного прерывания текущего CPU. |
esp_cpu_intr_has_handler |
Проверит, есть ли у определенного прерывания сконфигурированный обработчик (ISR). Проверка производится для определенного прерывания текущего CPU. Эта функция просто проверяет, есть ли в IVT текущего CPU назначенный для прерывания адрес обработчика. |
esp_cpu_intr_set_handler |
Установит функцию обработчика (ISR) для определенного прерывания на текущем CPU. Эта функция просто заполнит в таблице адресов векторов прерываний (IVT) адрес указанного прерывания без разрешения самого прерывания. |
esp_cpu_intr_get_handler_arg |
Извлечет адрес функции обработчика прерывания, который был ранее установлен для текущего CPU. |
esp_cpu_intr_enable |
Разрешит определенные прерывания на текущем CPU. |
esp_cpu_intr_disable |
Запретит определенные прерывания на текущем CPU. |
esp_cpu_intr_get_enabled_mask |
Извлечет разрешенные прерывания на текущем CPU. |
esp_cpu_intr_edge_ack |
Подтвердит прерывание по перепаду (edge interrupt). |
esp_cpu_configure_region_protection |
Сконфигурирует CPU для запрета доступа в неправильные области памяти. |
esp_cpu_set_breakpoint |
Установит и разрешит аппаратную точку останова (hardware breakpoint) на текущем CPU. Эта функция должна вызываться обработчиком паники (panic handler), чтобы установить breakpoint для подключенного отладчика во время возникновения паники ядра. Перезапишет ранее установленный breakpoint с таким же номером. |
esp_cpu_clear_breakpoint |
Очистит аппаратную точку останова (hardware breakpoint) на текущем CPU. Точка останова очищается независимо от того, была ли она установлена ранее. |
esp_cpu_set_watchpoint |
Установит и разрешить аппаратную точку отслеживания изменения памяти (hardware watchpoint) на текущем CPU. Установка и разрешение hardware watchpoint происходит с указанием диапазона адресов и операции для срабатывания точки отслеживания. Watchpoint-ы будут вызывать break/panic ядра CPU, когда оно обрабатывает (осуществляет доступ в соответствии с установленным типом срабатывания) определенный диапазон ячеек памяти. Перезапишет ранее установленный watchpoint с таким же номером. |
esp_cpu_clear_watchpoint |
Очистит hardware watchpoint на текущем CPU независимо от того, была ли ранее установлена эта watchpoint. |
esp_cpu_dbgr_is_attached |
Проверяет, подключен ли отладчик к текущему CPU. |
esp_cpu_dbgr_break |
Вызовет срабатывание вызова подключенного отладчика текущего CPU. |
esp_cpu_get_call_addr |
По указанному адресу возврата вычисляет адрес предыдущей вызывающей функции (которая вызвала инструкцию call). Эта функция обычно используется для ответа на вопрос "откуда была вызвана функция?". |
esp_cpu_compare_and_set |
Атомарная операция сравнения и установки (compare-and-set). |
Заголовочный файл: components/esp_app_format/include/esp_app_desc.h |
esp_app_get_description |
Возвратит структуру esp_app_desc. Эта структура возвратит версию приложения. Возвращается описание для работающего приложения. |
esp_app_get_elf_sha256 |
Заполнит предоставленный буфер значением SHA256 из ELF-файла, в виде форматированной HEX-строки, завершаемой нулем (ASCIIZ). Если размер буфера недостаточен, чтобы уместить все данные SHA256 в HEX плюс символ 0, то будет записано максимально возможное количество символов и завершающий 0. |
[Ссылки]
1. ESP32-C3 Miscellaneous System API site:espressif.com. 2. ESP32-C3: выделение памяти из кучи. 3. ESP32-C3 Ethernet site:espressif.com. 4. MAC address site:en.wikipedia.org. 5. ESP32: процесс запуска приложения. 6. ESP-IDF Build System. 7. ESP-IDF: формат файла образа приложения. |