Привет,
Это совместная работа: моя и мистера ChatGPT. Изначально этот текст был написан на англиском и мне було жутко лень его переписывать, я попросил Чатика перевести.
Ну и таблички мои корявые он перерисовал. Вроде не накосячил нигде.
Скрытый механизм уведомлений WiFi. Мигать светодиодиками можно!
ESP32-S3 (и другие ESP32 с встроенным WiFi) имеют скрытый механизм, который Espressif использует для отладки своей RF-подсистемы.
Помимо отладки, его можно использовать для создания светодиодных индикаторов состояния устройства - примерно как светодиоды на домашнем WiFi-роутере.
WiFi-стек ESP32 позволяет установить обработчик (hook), который вызывается драйвером WiFi при определённых событиях:
static int wifi_hook(int x, int y); // --> ваша функция-обработчик
extern void wifi_set_gpio_debug_cb(void *handler); // скрытый API ESP-IDF для установки обработчика
После установки обработчик начинает вызываться довольно часто во время нормальной работы WiFi. Если выполнять в нём что-то медленное, это замедлит весь WiFi-стек.
Функция получает два параметра - небольшие целые числа, определяющие тип события.
Судя по именам функций и диапазонам аргументов, я предполагаю, что параметр x когда-то использовался как номер GPIO, а y содержал данные, которые нужно было вывести на этот GPIO.
Вместо этого мы можем подключить светодиоды к произвольным GPIO и включать/выключать их, получая наглядную индикацию состояния устройства без всяких printf ![]()
Теперь о параметрах x и y, которые передаются в наш обработчик. Не запутайтесь в описаниях ниже - ориентируйтесь прежде всего на раздел Интерпретация.
Low MAC: события передачи кадров
| X | Y | Описание |
|---|---|---|
| 8 | 2 | Вызывается каждый раз, когда программное обеспечение пытается передать кадр через esp_wifi_internal_tx() или esp_wifi_internal_tx_by_ref(), непосредственно перед помещением кадра в очередь передачи. Интерпретация: программное событие отправки WiFi кадра. Драйвер отправил ваш пакет в железо. |
| 9 | 2 | Вызывается из lmacTxFrame() непосредственно перед hal_mac_txq_enable(). Интерпретация: аппаратная передача WiFi началась |
| 10 | 4 | Вызывается функцией ppTask() сразу после lmacProcessCollisions_task(). Интерпретация: обнаружена коллизия WiFi |
| 10 | 2 | Вызывается из lmacProcessTxComplete() перед началом обработки. Интерпретация: аппаратная передача завершена |
| 10 | 3 | Вызывается из lmacProcessTxComplete() перед началом обработки. Интерпретация: то же самое - аппаратная передача завершена |
Low MAC: приём кадров
| X | Y | Описание |
|---|---|---|
| 11 | >1 | Вызывается из IndicateFrame(). Буфер памяти успешно выделен. Указывает, что получен корректный WiFi-кадр и он передан в механизмы LMAC. Также означает, что кадр предназначен нам. Интерпретация: приём данных или получен корректный кадр |
| 12 | ?? | Вызывается из IndicateFrame() перед DiscardFrame(), указывая на проблему с выделением памяти. Это событие возникает только при нехватке памяти и не является общим индикатором отброшенных пакетов. Интерпретация: кадр отброшен из-за нехватки памяти (критическая ситуация) |
IEEE80211: высокоуровневые события
| X | Y | Описание |
|---|---|---|
| 13 | 2 | Вызывается из ieee80211_hostap_send_beacon_process() непосредственно перед ic_tx_pkt() для передачи заранее подготовленного маяка (beacon). Происходит часто. Только в режиме AP или AP+STA. Интерпретация: передача маяка SoftAP, точка доступа работает |
| 15 | 0 | Начато сканирование |
| 14 | 2 | Сканирование выполняется, периодические вызовы |
| 15 | 1 | Сканирование завершено |
Учитывая количество и плотность вызовов из модуля PowerManager, я начинаю подозревать, что весь этот механизм создавался прежде всего для отладки энергосбережения ![]()
PowerManager
Процедуры пробуждения и сна
| X | Y | Описание |
|---|---|---|
| 17 | 0 | Вызывается после pm_wake_up(). Интерпретация: начат процесс пробуждения |
| 17 | 1 | Вызывается перед pm_wake_done(). Интерпретация: процесс пробуждения завершён |
Здесь Espressif немного усложняет картину.
Используется последовательность из трёх последовательных вызовов.
Гарантируется, что эта последовательность не будет перемешана с другой, поскольку все вызовы выполняются из контекста WiFi-задачи, которая сериализует доступ к WiFi API. (Один большой глобальный лок на всё. Напоминает сетевые стеки BSD-происхождения в RTEMS образца примерно 2005 года.)
Последовательность №1
| X | Y |
|---|---|
| 3 | 1 |
| 4 | 1 |
| 5 | 0 |
Наблюдается в конце следующих функций:
pm_start()pm_disconnected_start()pm_disconnected_wake()
Интерпретация: какой-то процесс пробуждения (точное назначение неясно)
Последовательность №2
| X | Y |
|---|---|
| 3 | 0 |
| 4 | 1 |
| 5 | 1 |
Наблюдается в:
pm_disconnected_sleep()pm_disconnected_stop()
Интерпретация: какой-то процесс перехода в сон (точное назначение неясно)
Отслеживание изменений состояния внутреннего конечного автомата
Последовательность из двух вызовов выполняется каждый раз, когда модуль PM переходит из состояния old_state в состояние new_state.
Состояния нумеруются в диапазоне [0..5].
Знак «минус» означает обычное вычитание, поэтому значение аргумента X также лежит в диапазоне [0..5].
Гарантируется, что эта последовательность не будет прервана другой аналогичной последовательностью.
| X | Y |
|---|---|
| 5 - old_state | 1 |
| 5 - new_state | 0 |
Интерпретация: PowerManager выполняет работу
Активность, связанная с маяками
| X | Y | Описание |
|---|---|---|
| 0 | 2 | TBTT (Target Beacon Transmission Time). Интерпретация: аппаратное пробуждение для передачи или приёма маяков |
| 1 | 2 | Интерпретация: начало обработки маяка |
| 2 | 2 | Интерпретация: маяк не был получен в ожидаемое время |
Понятно не до конца
| X | Y | Описание |
|---|---|---|
| 6 | >1 | Пока нет никаких идей |
| 16 | 2 | Возникает одновременно с документированным WiFi-событием 0x16 (см. документацию ESP-IDF по WiFi) |
События подсистемы Coexist (RF-арбитр / планировщик BT, BLE и WiFi)
Эти события можно использовать для поиска проблем, связанных с совместной работой радиоподсистем.
| X | Y | Описание |
|---|---|---|
| 7 | 0 | RF-арбитр работает и распределяет временные интервалы между BT и WiFi. Имеет смысл только когда обе подсистемы активны. Интерпретация: тик планировщика совместного использования радио |
| 7 | 1 | Что-то связанное с процедурой временного разделения радиоэфира. Может использоваться как индикатор того, что coexist_schm функционирует. |
Минимальный пример для Arduino
#include <Arduino.h>
extern "C" {
void wifi_set_gpio_debug_cb(void *handler);
};
static int wifi_hook(int x, int y) {
esp_rom_printf("\r\nWIFI-GPIO-DEBUG: X=%d, Y=%d\r\n", x, y);
return 0;
}
void setup() {
Serial.begin(115200);
wifi_set_gpio_debug_cb((void *)wifi_hook);
// Инициализируйте WiFi здесь, иначе ваш обработчик никогда не будет вызван :)
}
void loop() {
delay(1000);
}