Программирование ARM Библиотека ESP-IDF для вывода в лог Wed, March 18 2026  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


Библиотека ESP-IDF для вывода в лог Печать
Добавил(а) microsin   

Библиотека лога предоставляет 2 способа установки подробности вывода информации (verbosity level):

· В момент компиляции (compile time): в menuconfig установить verbosity level по умолчанию, используя опцию CONFIG_LOG_DEFAULT_LEVEL.
· Опционально, также в menuconfig, установите максимальный уровень подробности (maximum verbosity level), используя опцию CONFIG_LOG_MAXIMUM_LEVEL. По умолчанию она имеет такое же значение, что и CONFIG_LOG_DEFAULT_LEVEL, однако её можно установить на более высокий уровень, чтобы скомпилировать в firmware больше опциональных логов.
· Во время работы приложения (runtime): все логи, у которых уровни подробности меньше, чем CONFIG_LOG_DEFAULT_LEVEL, по умолчанию разрешены. Функция esp_log_level_set() может использоваться для установки уровня подробности лога в пределах одного модуля (файла исходного кода). Модули идентифицируются по своим тегам, которые являются удобочитаемыми строками ASCIIZ.

Существуют следующие уровни подробности лога (verbosity level):

· Error (самый низкий уровень, выводятся только ошибки)
· Warning
· Info
· Debug
· Verbose (самый высокий уровень подробности вывода)

Замечание: функция esp_log_level_set() не может установить уровни подробности лога выше, чем это указано опцией CONFIG_LOG_MAXIMUM_LEVEL. Чтобы увеличить уровень лога для определенного файла выше этого максимума в момент компиляции, используйте макрос LOG_LOCAL_LEVEL (подробнее об этом см. далее).

[Как использовать библиотеку лога ESP-IDF]

В каждом C-файле (модуле), в котором используется лог, определите переменную TAG, как показано ниже:

static const char* TAG = "MyModule";

Затем используйте макросы вывода, например:

ESP_LOGW(TAG, "Baud rate error %.1f%%. Requested: %d baud, actual: %d baud",
              error * 100, baud_req, baud_real);

Доступны несколько макросов для разных уровней подробности вывода:

ESP_LOGE - error (самый низкий уровень)
ESP_LOGW - warning
ESP_LOGI - info
ESP_LOGD - debug
ESP_LOGV - verbose (самый высокий уровень)

Эти макросы отличаются друг от друга двумя моментами: во-первых, будет или не будет выведено макросом сообщение, зависит от текущего установленного уровня подробности. Во-вторых, отличается цвет текста выводимых сообщений в команде idf.py monitor. Например, ESP_LOGI выведет сообщение зеленым текстом, ESP_LOGW желтым текстом, а ESP_LOGE красным текстом.

Дополнительно существуют версии ESP_EARLY_LOGx для этих макросов, например ESP_EARLY_LOGE. Эти версии явно используются только в коде раннего запуска (startup), до того момента, как инициализируется куча (heap allocator) и системные вызовы (syscalls). Обычные макросы ESP_LOGx могут также использоваться, когда компилируется bootloader, однако для них произойдет откат обратно к той же реализации, что и у макросов ESP_EARLY_LOGx.

Также существуют версии ESP_DRAM_LOGx этих макросов, например ESP_DRAM_LOGE. Эти версии используются в некоторых местах, где вывод в лог может привести в условиях запрещенных прерываний, или когда кэш памяти flash недоступна. Использование этих макросов должно быть максимально щадящим, поскольку вывод в лог на таких местах кода вообще следует избегать по соображениям производительности.

Замечание: внутри критических секций кода прерывания запрещены, так что можно использовать только лишь ESP_DRAM_LOGx (что предпочтительнее) или ESP_EARLY_LOGx. Несмотря на то, что есть возможность использовать такой лог в этих ситуациях, лучше всего хорошо структурировать программу, чтобы это вовсе не потребовалось.

Чтобы отменить уровень подробности лога по умолчанию для области файла или области компонента, определите макрос LOG_LOCAL_LEVEL.

Для области файла определите этот макрос перед подключением esp_log.h, например:

#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"

В области компонента определите его в файле CMakeLists компонента:

target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE")

Уровни лога определены в заголовке esp-idf/components/log/include/esp_log_level.h:

/**
* @brief Log level
*/
typedef enum {
ESP_LOG_NONE = 0, /*!< Лог отключен */
ESP_LOG_ERROR = 1, /*!< Критические ошибки, программный модуль не может
восстановиться самостоятельно */
ESP_LOG_WARN = 2, /*!< Условия, при которых ошибка не критична, или могут
быть предприняты меры по восстановлению */
ESP_LOG_INFO = 3, /*!< Информационные сообщения, описывающие нормальное
течение событий */
ESP_LOG_DEBUG = 4, /*!< Дополнительная информация, которая не бывает нужна
для обычного использования (значения, указатели,
размеры, и т. п.). */
ESP_LOG_VERBOSE = 5, /*!< Большие порции отладочной информации или частые
сообщения, которые могут потенциально переполнить
вывод. */
ESP_LOG_MAX = 6, /*!< Количество поддерживаемых уровней лога */ } esp_log_level_t;

Для конфигурирования вывода в области модуля runtime, добавьте вызовы функции esp_log_level_set() следующим образом:

esp_log_level_set("*", ESP_LOG_ERROR);        // установить уровень ERROR для всех компонентов
esp_log_level_set("wifi", ESP_LOG_WARN);      // разрешить логи WARN для стека WiFi
esp_log_level_set("dhcpc", ESP_LOG_INFO);     // разрешить логи INFO из клиента DHCP

Замечание: варианты макросов лога "DRAM" и "EARLY", упомянутые выше, не поддерживают установку подробности вывода в лог в области модуля. Эти макросы всегда будут использовать verbosity level по умолчанию, который можно поменять runtime только вызовом esp_log_level("*", level).

В качестве первого параметра указывается текстовый идентификатор драйвера (const char* tag), для которого задается уровень лога. Этот идентификатор определен в соотетствующем модуле драйвера. В следующей таблице приведены идентификаторы некоторых драйверов.

Модуль драйвера tag (идентификатор драйвера)
touch_sensor_common.c static const char *TOUCH_TAG = "TOUCH_SENSOR";
i2c.c static const char *I2C_TAG = "i2c";
timer_legacy.c static const char *TIMER_TAG = "timer_group";
adc_legacy.c static const char *ADC_TAG = "ADC";
adc_dma_legacy.c static const char *ADC_TAG = "ADC";
clk_tree_hal.c static const char *CLK_HAL_TAG = "clk_hal";
adc_continuous.c static const char *ADC_TAG = "adc_continuous";
adc_monitor.c static const char *MNTOR_TAG = "adc_monitor";
spi_share_hw_ctrl.c static const char* SPI_TAG = "spi_share_hw_ctrl";
spi_master.c static const char *SPI_TAG = "spi_master";
spi_slave.c static const char *SPI_TAG = "spi_slave";
spi_common.c static const char *SPI_TAG = "spi";
ulp_riscv_i2c.c static const char *RTCI2C_TAG = "ulp_riscv_i2c";
lp_core_uart.c static const char *LP_UART_TAG = "lp_uart";
lp_core_i2c.c static const char *LPI2C_TAG = "lp_core_i2c";
lp_core_spi.c static const char *LP_SPI_TAG = "lp_spi";
roaming_app.c static const char *ROAMING_TAG = "ROAM";
gpio.c static const char *GPIO_TAG = "gpio";
rtc_io.c static const char __attribute__((__unused__)) *RTCIO_TAG = "RTCIO";
usb_phy.c static const char *USBPHY_TAG = "usb_phy";
lp_i2s_vad.c static const char *LP_VAD_TAG = "LP_VAD";
uart.c static const char *UART_TAG = "uart";
usb_serial_jtag.c static const char* USB_SERIAL_JTAG_TAG = "usb_serial_jtag";

Лог на хост через JTAG. По умолчанию библиотека лога использует функцию наподобие vprintf для форматированного вывода в выделенный для программирования и лога UART. Вместо этого простым API-вызовом вывод может быть перенаправлен в JTAG, что сделает вывод в лог в несколько раз быстрее. За подробностями обратитесь в раздел "Logging to Host" документации [2].

[Пример приложения]

Библиотека лога используется в большинстве компонентов примеров и примеров ESP-IDF как основной метод отладки и поиска ошибок. Для демонстрации функционала вывода в лог просмотрите содержимое директории examples каталога установки ESP-IDF. Наиболее подходящие примеры для исследования работы лога:

system/ota
storage/sd_card
protocols/https_request

[Справочник по API]

Заголовочный файл библиотеки лога components/log/include/esp_log.h.

В следующей таблице приведен общий список API-функций и макросов лога с кратким описанием. Подробное описание с назначением параметров, возвращаемых значений, типов данных см. в документации [1].

API-функции

Функция Описание
esp_log_level_set Установит уровень лога для указанного тега. Если лог для указанного компонента был уже разрешен, то эта функция поменяет предыдущую настройку.
esp_log_level_get Получит уровень лога для указанного тега, может использоваться для устранения лишних операторов лога.
esp_log_set_vprintf Установит функцию, используемую для вывода элементов лога. По умолчанию вывод лога производится в UART0 (лог доступен в терминале командой idf.py monitor). Эта функция может использоваться для перенаправления вывода лога в некоторые другие устройства, такие как файл или сеть. Возвратит оригинальный обработчик лога, который может понадобиться для возврата предыдущего направления вывода лога.
esp_log_timestamp Функция, которая вернет метку времени, используемую для вывода в лог. Эта функция используется в расширении макросов ESP_LOGx. На стадии загрузчика второй ступени (2nd stage bootloader) и коде раннего запуска приложения (early application startup) эта функция использует счетчик тактов CPU как источник отсчета времени. Позже, когда заработает планировщик FreeRTOS, про метка времени для лога будет извлекаться из счетчика тиков FreeRTOS. Для отладочного вывода в лог абсолютного времени в настоящий момент переполнение этого счетчика игнорируется.
esp_log_system_timestamp Функция, которая берет системную метку времени для использования в выводе лога. Эта функция используется в макросах ESP_LOGx, чтобы печатать системное время в виде "HH:MM:SS.sss". Системное время инициализируется на 0 в момент startup, оно может быть установлено на корректное время с помощью синхронизации SNTP, или вручную стандартными POSIX-функциями времени. В настоящий момент это не будет использоваться для вывода в лог из двоичного кода (например библиотек Wi-Fi и Bluetooth), оттуда будет печататься время тиков RTOS (что для отслеживания интервалов времени часто удобнее формата HH:MM:SS.sss).
esp_log_early_timestamp Функция, которая берет системную метку времени для использования в выводе лога. Эта функция использует аппаратный счетчик тактов, и не зависит от реализации OS, так что может безопасно использоваться после краха приложения.
esp_log_write Запись сообщения в лог. Эта функция не предназначена для прямого использования. Вместо неё вызывайте макросы ESP_LOGE, ESP_LOGW, ESP_LOGI, ESP_LOGD, ESP_LOGV. Эта функция и эти макросы не должны использоваться в коде обработчика прерывания (ISR).
esp_log_writev Запись сообщения в лог, организованный в виде списка (вариант va_list). Эта функция предоставлена для упрощения интеграции в другой фреймворк лога, чтобы esp_log можно было использовать как точку слива в лог.

Макросы

Макрос Описание
ESP_LOG_BUFFER_HEX_LEVEL Вывод в лог содержимого буфера в виде HEX-значений байт, по 16 байт на каждой строке, на указанном уровне подробности лога LEVEL.
ESP_LOG_BUFFER_CHAR_LEVEL Вывод в лог содержимого буфера в виде символов, по 16 байт на строке, на указанном уровне подробности лога LEVEL. Буфер должен содержать только печатаемые символы.
ESP_LOG_BUFFER_HEXDUMP Дамп буфера в лог на указанном уровне подробности. Выводит и HEX значения, и соответствующие ASCII символы, по 16 байт в строке.
ESP_LOG_BUFFER_HEX Вывод в лог содержимого буфера в виде HEX-значений байт, на уровне подробности Info.
ESP_LOG_BUFFER_CHAR Вывод в лог содержимого буфера в виде ASCII-символов, на уровне подробности Info. Буфер должен содержать только печатаемые символы.
ESP_EARLY_LOGE Макрос для вывода в лог из кода startup, до момента инициализации heap allocator и syscalls. Выводит в лог на уровне ESP_LOG_ERROR.
ESP_EARLY_LOGW То же самое, только на уровне ESP_LOG_WARN.
ESP_EARLY_LOGI То же самое, только на уровне ESP_LOG_INFO.
ESP_EARLY_LOGD То же самое, только на уровне ESP_LOG_DEBUG.
ESP_EARLY_LOGV То же самое, только на уровне ESP_LOG_VERBOSE.
ESP_LOGE(tag, format, ...)
ESP_LOGW(tag, format, ...)
ESP_LOGI(tag, format, ...)
ESP_LOGD(tag, format, ...)
ESP_LOGV(tag, format, ...)
ESP_LOG_LEVEL(level, tag, format, ...)
Макросы, вызываемые из обычного кода для вывода в лог на указанном уровне подробности.
ESP_LOG_LEVEL_LOCAL Макрос, вызываемый из обычного кода для вывода в лог на указанном уровне подробности. Также проверяйте уровень подробности с помощью LOG_LOCAL_LEVEL.
ESP_DRAM_LOGE Макрос для вывода в лог, когда кэш запрещен. Выводит в лог на уровне ESP_LOG_ERROR.
ESP_DRAM_LOGW То же самое, только на уровне ESP_LOG_WARN.
ESP_DRAM_LOGI То же самое, только на уровне ESP_LOG_INFO.
ESP_DRAM_LOGD То же самое, только на уровне ESP_LOG_DEBUG.
ESP_DRAM_LOGV То же самое, только на уровне ESP_LOG_VERBOSE.

[Настройки уровня лога в idf.py menuconfig]

Настройка idf.py menuconfig:

ESP IDF menuconfig component Log

Для чего нужны параметры "Default log verbosity" и "Maximum log verbosity"?

Представьте себе фильтр для ваших логов. Один параметр решает, какие сообщения будут видны сразу после запуска, а другой — какие сообщения в принципе могут быть показаны, если вы решите изменить настройки позже.

Default log verbosity (уровень логирования по умолчанию)

Этот параметр устанавливает уровень детализации, с которым система будет писать логи сразу после запуска (и во время компиляции). Все сообщения с уровнем выше (т.е. менее детальные), чем выбранный, будут выводиться. Сообщения с уровнем ниже (более детальные) будут по умолчанию отключены.

● Где используется: работает на этапе компиляции и как настройка по умолчанию при старте программы.
● Что можно выбрать: уровни идут от самого грубого (Error, только ошибки) до самого подробного (Verbose, буквально всё).

Например, если вы выставите значение `Info`, то в логах вы увидите сообщения `Error`, `Warning` и `Info`. Сообщения `Debug` и `Verbose` будут скрыты, но их можно будет включить позже (см. следующий пункт).

Maximum log verbosity (максимальный уровень логирования)

Этот параметр определяет "потолок" детализации, который в принципе доступен в прошивке. Другими словами, он задает, какие уровни логов будут скомпилированы и включены в бинарный файл прошивки.

● Где используется: исключительно на этапе компиляции. Это позволяет не включать в прошивку код для самых детальных логов, если вы уверены, что они вам никогда не понадобятся, экономя место в памяти.
● Важное ограничение: никакая функция, включая esp_log_level_set(), не сможет включить уровень логирования, который выше этого значения.

Например, вы установили `Maximum log verbosity` в значение `Info`. Это значит, что сообщения уровней `Debug` и `Verbose` не будут скомпилированы в прошивку. Даже если вы очень захотите их увидеть и вызовете специальную функцию, они не появятся, потому что их физически нет в коде.

Взаимосвязь параметров на простом примере

Чтобы стало совсем понятно, представьте себе "лестницу" уровней логирования:

Уровень 5: `Verbose` (самый подробный)
Уровень 4: `Debug`
Уровень 3: `Info`
Уровень 2: `Warning`
Уровень 1: `Error` (самый грубый)

1. Вы включаете в `menuconfig` `Default log verbosity = Warning`, `Maximum log verbosity = Verbose`.

Что на выходе: в прошивку будут скомпилированы сообщения всех уровней (от Error до Verbose). Однако, сразу после запуска вы будете видеть только `Error` и `Warning`. Если вам понадобится отладить какую-то проблему, вы можете в коде с помощью `esp_log_level_set()` временно включить для нужного модуля уровень `Debug` или `Verbose`, и они начнут выводиться.

2. Вы включаете в `menuconfig` `Default log verbosity = Warning`, `Maximum log verbosity = Info`.

Что на выходе: в прошивку будут скомпилированы только сообщения уровней `Error`, `Warning` и `Info`. Уровни `Debug` и `Verbose` будут вырезаны. Сразу после запуска вы будете видеть `Error` и `Warning` (как и в прошлом примере). Но теперь, как бы вы ни старались, вы никогда не сможете увидеть сообщения `Debug` и `Verbose`, потому что их код не был включен в прошивку .

Таким образом, `Default log verbosity` управляет тем, что вы видите "сейчас", а `Maximum log verbosity` — тем, что вы потенциально можете увидеть "вообще".

[Ссылки]

1. ESP-IDF Logging library site:espressif.com.
2. ESP-IDF Application Level Tracing library site:espressif.com.

 

Добавить комментарий


Защитный код
Обновить

Top of Page