
48
Включаем функции сбора статистики в ESP32-arduino
Дополненная версия статьи на habr.
Основная проблема в том, что в исходной собранной библиотеке arduino-esp32 функции сбора статистики (vTaskGetRunTimeStats
/ vTaskList
) отключены. Библиотека используется как есть в Platformio, ссылки на гайды по сборке своих библиотек устарели (404), а актуальных доступных всем инструкций просто нет. К тому же issues по добавлению этих функций также не рассматривают, т.к. они связаны с использованием сторонней библиотеки.
Чтобы добавить эти функции - нужно пересобрать библиотеку с измененными параметрами. В качестве OS используем Ubuntu (windows - пользователи могут поднять виртуалку в WSL).
Esp32 arduino lib builder
Инструкция установке билдера и сборке есть на официальном сайте. Устанавливаем зависимости:
sudo apt-get install git wget curl libssl-dev libncurses-dev flex bison gperf cmake ninja-build ccache jq python3
sudo pip install --upgrade pip
pip install --user setuptools pyserial click cryptography future pyparsing pyelftools
Можно дальше по инструкции клонировать репозиторий и запустить сборку. Чтобы вы понимали - скачивание всех зависимостей и сборка занимают примерно час.
А потом результаты сборки можете ... выкинуть, потому что версии самого билдера и всех используемых библиотек отличаются и использовать их в Platformio не получится.
Нам нужны конкретные версии конкретных пакетов, билдер из коробки такой возможности не предоставляет, поэтому придется ему помочь. Актуальные версии пакетов, которые используются в Platformio, можно посмотреть в ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/version.txt
, у меня файл выглядит так:
esp-idf: v4.4.7 38eeba213a
arduino: idf-38eeba213a d75795f5
esp-dl: master 0632d24
esp-rainmaker: master d8e9345
esp32-camera: master f0bb429
esp_littlefs: master 41873c2
espressif__esp-dsp: master 9b4a8b4
tinyusb: master a0e5626bc
Каким-то чудом по хешу коммита версии одной из библиотек в Platformio удалось найти статью на японском (!), которая описывает, что действительно нужно сделать для пересборки библиотеки. Билдер мы ставили не зря, но вот дальше начинаются приключения - каждую из этих библиотек придется установить вручную.
Для начала все же клонируем билдер и переключим версию:
git clone https://github.com/espressif/esp32-arduino-lib-builder
cd esp32-arduino-lib-builder
git switch release/v4.4
Далее необходимо зафиксировать каждую версию библиотеки, поэтому нужно закомментировать в билдере автоматическое обновление компонентов (build.sh:84
):
84 #echo "* Installing/Updating ESP-IDF and all components..."
85 # update components from git
86 #./tools/update-components.sh
87 #if [ $? -ne 0 ]; then exit 1; fi
Теперь придется вручную загрузить все компоненты, включая ESP-IDF и ядро Arduino для ESP32 .
TLDR установка всех зависимостей в одну команду:
git clone -b v4.4.7 --recursive https://github.com/espressif/esp-idf.git && git -C ./esp-idf/ reset --hard 38eeba213a && git clone -b 2.0.17 --recursive https://github.com/espressif/arduino-esp32 ./components/arduino && git -C ./components/arduino reset --hard d75795f5 && git clone --recursive https://github.com/espressif/esp32-camera ./components/esp32-camera && git -C ./components/esp32-camera reset --hard f0bb429 && git clone --recursive https://github.com/espressif/esp-dl.git ./components/esp-dl && git -C ./components/esp-dl reset --hard 0632d24 && git clone --recursive https://github.com/joltwallet/esp_littlefs.git ./components/esp_littlefs && git -C ./components/esp_littlefs reset --hard 41873c2 && git -C ./components/esp_littlefs submodule update --init --recursive && git clone --recursive https://github.com/espressif/esp-rainmaker.git ./components/esp-rainmaker && git -C ./components/esp-rainmaker reset --hard d8e9345 && git -C ./components/esp-rainmaker submodule update --init --recursive && git clone --recursive https://github.com/espressif/esp-dsp.git ./components/espressif__esp-dsp && git -C ./components/espressif__esp-dsp reset --hard 9b4a8b4 && git clone --recursive https://github.com/hathach/tinyusb.git ./components/arduino_tinyusb/tinyusb && git -C ./components/arduino_tinyusb/tinyusb reset --hard a0e5626bc
Ниже разбивка по библиотекам и командам.
esp-idf
git clone -b v4.4.7 --recursive https://github.com/espressif/esp-idf.git
git -C ./esp-idf/ reset --hard 38eeba213a
arduino-esp32
git clone -b 2.0.17 --recursive https://github.com/espressif/arduino-esp32 ./components/arduino
git -C ./components/arduino reset --hard d75795f5
esp32-camera
git clone --recursive https://github.com/espressif/esp32-camera ./components/esp32-camera
git -C ./components/esp32-camera reset --hard f0bb429
esp-dl
git clone --recursive https://github.com/espressif/esp-dl.git ./components/esp-dl
git -C ./components/esp-dl reset --hard 0632d24
esp_littlefs
git clone --recursive https://github.com/joltwallet/esp_littlefs.git ./components/esp_littlefs
git -C ./components/esp_littlefs reset --hard 41873c2
git -C ./components/esp_littlefs submodule update --init --recursive
esp-rainmaker
git clone --recursive https://github.com/espressif/esp-rainmaker.git ./components/esp-rainmaker
git -C ./components/esp-rainmaker reset --hard d8e9345
git -C ./components/esp-rainmaker submodule update --init --recursive
espressif__esp-dsp
git clone --recursive https://github.com/espressif/esp-dsp.git ./components/espressif__esp-dsp
git -C ./components/espressif__esp-dsp reset --hard 9b4a8b4
tinyusb
git clone --recursive https://github.com/hathach/tinyusb.git ./components/arduino_tinyusb/tinyusb
git -C ./components/arduino_tinyusb/tinyusb reset --hard a0e5626bc
Сборка
Теперь можем запустить сборку для esp32 (если у вас другая ревизия платы - указывайте её):
./build.sh -t esp32
Сборка занимает продолжительное время, если по итогe создан каталог с именем «out» - операция прошла успешно.
$ ls out
package_esp32_index.template.json platform.txt tools
Sdkconfig
Если хотите, можете посмотреть текущие настройки sdkconfig:
. ./esp-idf/export.sh
idf.py menuconfig
Можно использовать menuconfig
только для просмотра настроек сборки, редактировать здесь настройки не выйдет.
Нужная мне опция находятся в Component config ---> FreeRTOS ---> Enable FreeRTOS to collect run time stats. Как видим, по умолчанию флаг сброшен:
Нужно внести изменения относительно стандартного sdkconfig. Для esp32 нужно отредактировать configs/defconfig.esp32
.
Для esp32c2 и esp32c3 результирующее имя файла — defconfig.esp32c2
и defconfig.esp32c3
соответственно (рядом можете найти и другие ревизии).
CONFIG_BTDM_CTRL_MODE_BTDM=y
CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE=20
CONFIG_BT_BTC_TASK_STACK_SIZE=8192
CONFIG_BT_BTU_TASK_STACK_SIZE=8192
CONFIG_BT_CLASSIC_ENABLED=y
CONFIG_BT_A2DP_ENABLE=y
CONFIG_BT_SPP_ENABLED=y
CONFIG_BT_HFP_ENABLE=y
CONFIG_BT_STACK_NO_LOG=y
CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y
CONFIG_ESP32_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_OCCUPY_HSPI_HOST=y
CONFIG_ESP32_ULP_COPROC_ENABLED=y
CONFIG_ESP32_XTAL_FREQ_AUTO=y
# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set
CONFIG_FREERTOS_FPU_IN_ISR=y
# CONFIG_USE_WAKENET is not set
# CONFIG_USE_MULTINET is not set
CONFIG_TWAI_ERRATA_FIX_BUS_OFF_REC=y
CONFIG_TWAI_ERRATA_FIX_TX_INTR_LOST=y
CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID=y
CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT=y
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
Я добавил последнюю строку для включения функций сбора статистики. Все прочие уже были в файле.
Собираем все заново:
./build.sh -t esp32
После завершения сборки заново проверяем конфиг сборки (каждый раз нужно экспортировать заново):
. ./esp-idf/export.sh
idf.py menuconfig
Если нужный флаг установлен - мы все сделали правильно.
Platformio
Осталось дело за малым, скопировать нашу библиотеку в Platformio.
Предварительно соxраняем исходную библиотеку и копируем собранную в Platformio:
mv -r ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/ ./platformio-sdk-backup/
cp -r ./out/tools/sdk ~/.platformio/packages/framework-arduinoespressif32/tools
Можно переходить в Platformio и попробовать собрать прошивку, функции должны быть доступны.
Вот такой минимальный код можно использовать для проверки:
#include <Arduino.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void TaskLog(void *pvParameters) {
static const int statsBufferSize = 1024;
static char statsBuffer[statsBufferSize];
static const int listBufferSize = 1024;
static char listBuffer[listBufferSize];
while (true) {
Serial.println("\n============ Task Stats ============");
// Get runtime stats for CPU usage
// This requires configGENERATE_RUN_TIME_STATS to be enabled
vTaskGetRunTimeStats(statsBuffer);
Serial.println("Run Time Stats:");
Serial.println(statsBuffer);
// Get task list with state, priority, stack, and task number
// Note: vTaskList output depends on configuration and may not include core affinities by default
vTaskList(listBuffer);
Serial.println("Task List:");
Serial.println(listBuffer);
Serial.println("=====================================");
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
void setup() {
// Инициализация последовательного порта
Serial.begin(115200);
Serial.println("ESP32 example with stats");
// Создание задачи для вывода логов на ядре 1
xTaskCreatePinnedToCore(
TaskLog, // Функция задачи
"Log", // Имя задачи
2048, // Увеличили размер стека для доп. вычислений
NULL, // Параметры задачи
1, // Приоритет задачи
NULL, // Дескриптор задачи
1 // Ядро, на котором будет выполняться задача
);
}
void loop() {
delay(1000);
}
Каждые 5 секунд в консоль выводится статистика по загрузке CPU каждой задачей, а также список задач:
============ Task Stats ============
Run Time Stats:
Log 11614 <1%
IDLE0 20176378 97%
IDLE1 20618561 99%
loopTask 1060 <1%
esp_timer 24 <1%
Tmr Svc 22 <1%
ipc1 47571 <1%
ipc0 32460 <1%
Task List:
Log X 1 624 10
IDLE0 R 0 552 5
IDLE1 R 0 548 6
loopTask B 1 7292 8
Tmr Svc B 1 1584 7
ipc1 B 24 484 2
ipc0 B 24 508 1
esp_timer S 22 4096 3
=====================================
Вот таким замысловатым способом вы можете менять параметры библиотеки esp32-arduino для использования в Platformio.
Список параметров значительно шире, чем включение функций получения статистики, жаль что IDE не предоставляют более удобный способ конфигурирования основных библиотек.
В решении этой задачи никакие ИИ-модели, к сожалению, не помогли, хотя я довольно упорно пытался заставить o1, sonnet 3.5 и o3-mini мне помочь. Старый добрый гугл, копание в архиве форумов и единственная статья по теме на японском (не перестаю удивляться этому факту) - все еще вполне рабочий пайплайн.
По крайней мере сейчас, по крайней мере для эмбеддинга.
Послесловие
Зачем вообще может понадобиться этот сбор статистики?
- Если вы хотите оптимизировать прошивку / быстродействие системы.
- Если вы хотите сравнить различные решения.
- Просто если интересно разобраться, как работают те или иные функции.
Изначально я собирался написать бенчмарк для esp32-cam (и пока окончательно от этого плана не отказался), где будут сравниваться различные протоколы передачи видеопотока / обратного управления для устройства. Для чего мне это - узнаете из следующих статей.
Но суть в том, что я уперся в невозможность получения статистики на arduino framework штатными средствами esp-idf, переключил платформу на esp-idf в Platformio и там настроил вывод статистики - это было чудесно.
Дальше я на esp-idf попробовал банально подключиться к wi-fi, открыл getting started и в ужасе закрыл, реализация настолько низкоуровневая по сравнению с библиотеками arduino, что я даже смотреть в сторону esp-idf больше не хочу.
Тем не менее, сбор статичтики мне покоя не давал и я написал простенький сбор своими руками, что-то такое:
TaskStats httpTaskStats = {"HTTP Server", 1, 0, 0, 0, 0, false};
void updateTaskStats(TaskStats &stats, bool startActive) {
unsigned long currentTime = micros();
unsigned long timeDiff = currentTime - stats.lastCheck;
if (startActive && !stats.isActive) {
stats.lastActive = currentTime;
stats.isActive = true;
}
else if (!startActive && stats.isActive) {
stats.activeTime += currentTime - stats.lastActive;
stats.isActive = false;
}
stats.totalTime += timeDiff;
stats.lastCheck = currentTime;
}
Ну т.е. через ручные вызовы в начале и конце задачи через micros() я пытался посчитать загрузку задачами по времени. Получилась вот такая статистика (те же 5 секунд):
Task Usage Statistics:
Blink (Core 0): 0.0066% (Active: 267 us / Total: 4021757 us)
HTTP Server (Core 1): 16.6422% (Active: 831341 us / Total: 4995383 us)
Log (Core 1): 0.0000% (Active: 0 us / Total: 5000384 us)
Помимо сложностей в разработке, учета только пользовательских задач - посмотрите на якобы загрузку от задачи http сервера, в разных кейсах она доходила до 50% без запросов. Причем если появлялся запрос на обработку - процент загрузки даже уменьшался.
А теперь сравните это с нормальной статистикой, полученной внутренней функцией:
HttpServer 1382186 <1%
Т.е. на самом деле эта задача почти ничего не потребляет. Здесь сказывается разница в учете времени - http сервер, насколько я понимаю, не занимает задачу все время ожидания запроса и работает через таймер / события / что-то там еще внутри. Кастомная реализация статистики этого, разумеется не учитывает и не может учитывать. Так что использовать её абсолютно бессмысленно.
UPD
Сообщество PlatformIO также предложило использовать pioarduino — форк платформы platform-espressif32, — чтобы включить поддержку последней версии Espressif32 Arduino 3.x в PlatformIO. Эта версия включает встроенную поддержку статистических функций. PlatformIO пока официально не поддерживает Arduino 3.x. Кроме того, между этими версиями есть довольно значительные различия.
Комментариев пока нет
-
Подарочный бокс с ИИ
Пришло то время, когда AI может не только отвечать в чатиках и применяться в di… -
Делаем картинки на сайте кликабельными
Я часто вставляю картинки в хорошем качестве, но до сих пор их нельзя было удоб… -
Включаем функции сбора статистики в ESP32-arduino
Речь пойдет о функциях FreeRTOS vTaskGetRunTimeStats / vTaskList, но таким же… -
Счетчик просмотров в Bolt CMS
Делаем счетчик просмотров для статей в Bolt CMS. Возможные варианты и базовая… -
Скрытый держатель дисков
Ищете куда деть свою коллекцию дисков, а складирование на полках считаете скучн… -
Student48
Для выпускников АСУ ЛГТУ 2014-2021 годов это название говорит о многом, давайте…