[ESP32S3 Undocumented] Бесплатный timestamp на ESP32

На ESP32 все таймстампы (и миллис() и микрос()) сводятся к вызову esp_timer_get_time(), который, вообще говоря, не маленький. Размер кода, я имею ввиду. Внезапно нашелся недокументированный адрес, относящийся к WiFi periferal, в котором тикают микросекунды. Вне зависимости от того используете ли вы WiFi или нет.

На ESP32-S3 этот адрес: 0x60035000. Значение timestamp - 32 бита.

volatile uint32_t *wifi_tsta = (uint32_t *)((uintptr_t)0x60035000);

printf("Time now: %lu\r\n",*wifi_tsta);
7 лайков

Это прикольно, но, как показывает практика, этим лучше не пользоваться. Это применимо в “одноразовых” кодах, но ни в коем случае не в кодах, которые должны жить и переходить из проекта в проект.

Вы фанат прям 32й, много интересного почерпнул. Но тут прям вопрос - насколько разница? В каких проектах вызов esp_timer_get_time() критичен? Для себя даже представить такого не могу. Тем более, в свидетелях переполнения millis, вы пропагандируете переходить от 64 к 32

1 лайк

не, “копатель” знатный :+1:

1 лайк

Ну само собой.

С другой стороны у нас же тут не программа для компутера. Прошивка и MCU обычно составляют одно изделие, в котором уже ничего меняться не будет без великой нужды. И прошивка точно знает, на каком железе она будет запущена..

Спойлер

Я сегодня посмотрю на других моделях этот адрес. Такой же или нет.

Адрес относится к модулю WiFi, в документации весь диапазон адресов помечен как reserved. Лицензированный WiFi стек у них. Низя раскрывать документацию, а то хакеры отовсюду повылазят. Типа.

Адрес этот, судя по всему меняться не будет, т.к. прошивка в ROM его тоже использует, а ROM перепрошить нельзя.

Я затеял глупость, что пытались многие, но пока ни у кого не вышло: реверсю closed-source драйвер WiFi в ESP32. Там очень много файлов - под сотню. Я пытаюсь зареверсить их так, чтобы потом можно было скомпилировать и использовать.

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

К счастью, в ROM остались вызовы для логгирования (текстовые строчки, типа, “crypto ID %x is wrong“). По этим строчкам восстанавливаю название и смысл параметров. С сайта espressif скачал оригинал прошивки в ROM - она у них лежит как .elf с debug info. Прям спасибо, дорого Еспрессиф.

Но с регистрами совсем жопа. Пока точно нашел регистры инит MAC\деинит MAC\ packet CRC\ DMA descriptors\флаги готовности, ожидания и т.п. Задокументировать регистры мне на самом деле хочется даже больше, чем создать компилябельную версию драйвера.

Эх…

Нашел и багу. Но она, скорее всего, неинтересная - там можно вызовом к ROM WiFi API записать произвольные данные в произвольное место DRAM. Пока не придумал, для чего это может пригодиться. Они не проверяют параметр и используют его как индекс массива глобального. Со всеми вытекающими.

Чатика ЖПТ привлек, помогает. В основном мы с ним гадаем откуда пригла та или иная функция, судя по ее названию: часть там от NetBSD, например.

1 лайк

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

Не знаю. Давайте высасывать из пальца.

Спойлер

Ну, например, вы пишите какой-то код, который должен исполняться быстро, но вызов esp_timer_get_time() вам постоянно дает icache miss.

Т.е. у вас в коде работают функции, сгрупированные в кучку, промаха по кешу нет, все быстро. Потом кто-то вызвал esp_timer_get_time(), процессор понял, что функция эта лежит где-то совсем в стороне и дает команду загрузить в кэш эту новую память (16 или 32 кб). Отработала - опять icache miss. Так и будет дергать туда-сюда

Вот еще генератор случайных чисел НЕ связанный с аппаратным RNG ( в ESP32 есть HW RNG)

0x6003507c

Драйвер обращается к этой памяти так:

uint32_t hal_random(void) {

  asm (“memw“);   // дождаться завершения всех отложенных операций с памятью.

  return *(uint32_t *)(uintptr_t)0x6003507c;
}
1 лайк

И последнее на сегодня сообщение в теме. Смотрите, какую любопытную фигню нашел. Тоже недокументированно ничего совсем.

Смотреть в правый верхний угол, названия функций. Интересно, для кого это было предусмотрено и зачем.

Очень похоже на кусок отладчика.

На оригинальном ESP32 (все, что было выше - это про ESP32-S3) адреса другие.

Timestamp: 0x3ff73c00

Random: 0x3ff75144

Дополнительно выяснилось, что функции

uint32_t hal_random();
uint32_t hal_now():

Присутствуют в ПЗУ ESP32, ESP32-S2 и ESP32-S3. Так что можно не забивать себе голову адресами, а писать в своем скетче, например, так:

// Это будет работать на процессорах Xtensa (esp32, s2 и s3)
//
#include <stdint.h>

extern "C" uint32_t hal_random();
extern "C" uint32_t hal_now();

...
...
Serial.printf("Random number: %08x, time now: %08x\r\n", 
                (unsigned int)hal_random(),
                (unsigned int)hal_now());
...
...

Вот и я ж про то же :slight_smile:

Это уже ближе к делу. Надеюсь, они на любом чипе правильно работают?

Судя по всему. Я посмотрел ROM всех ESPшек на архитектуре Xtensa, там везде в ROM эти функции есть. При случае сравню их работу и работу esp_timer_get_time().

Это интерфейсные функции, которые использует WiFi код. Он ставит таймстампы в пакеты и использует свой RNG. Надо бы выдоить массив килобайт на сто из этого RNG и скормить его online checker. Посмотреть, насколько он RNG.

Эъ, найти бы какую-нибудь софтину, которая бы мне весь call graph нарисовала.. Ghidra (дизассемблер) умеет, но только в пределах одного TU (одного файла). А у меня сто файлов. Кроме как напечатать каждый файл на листе, потом все это пришпилить на ватман и дорисовать стрелки в голову ничего не приходит

Такое, только разом по всем файлам.

у Espressif две линейки чипов:

  1. На архитектуре Xtensa (весьма необычная архитектура, чем-то напоминает старый SPARC) от Tensilica (Cadence). Их я проверил.

  2. На RISCV: ESP32-C3,C6,C61,H2,P4 - их я не проверял. Купил, но не доехали еще. Мне самому интересно, тот же WiFi IP core используется или другой.

У кого Espressif лицензировал WiFi ядро свое - непонятно. Так же пока непонятно, одинаковые ли WiFi ядра стоят на вышеперечисленных линейках или на RISCV они воткнули что-то другое. По манере именования функций похоже на Broadcom.

Если бы только узнать, чье ядро они вкорячили, то можно было бы поискать в интернете альтернативные источники информации о назначении регистров и флагов в них. В жизни не поверю, что их код не слит в сеть.

Я думаю, для многих будет новостью, КАК устроена обработка ошибок в WiFi драйвере ESP32

Никак.

Например, полно кода, который вызывает malloc() и, если результат - NULL, то

  1. отправляется сообщение во внутренний лог (кольцевой буффер в памяти, при записи в которую так же может вызваться malloc()!!!) и..

  2. уходит в бесконечный цикл.

Мудро. Тут даже watchdog, я думаю, может не помочь. Просто тихо повисает, без возможности прочитать тот же самый лог. Который прочитать можно только из памяти - не существует функций чтения лога. Только руками.

Короче, это плохо очень. Если железка необслуживаемая повиснет, придется ехать в командировку и перезагружать вручную, что-ли.

Типичный код:

    if ((uVar5 >> 4 & 0xf) != uVar4) {
      wifi_log(6,0x800,1,"%s %u\n",&DAT_0001027a,0x38f);
      do {
                    /* WARNING: Do nothing block with infinite loop */
      } while( true );
    }

Половина кода такого, половина - хорошего. И стиль разный, что намекает на две группы разработчиков. Код написанный программистами Espressif - хороший. Чуваки знают, что делают. А вот другой код (например, packet processing engine) - корявый. Судя по всему, помимо лицензированного железа WiFi они еще и купили чей-то софт, дописали прослойку и склеили все вместе китайским клеем самым лучшим

Забавно еще то, что все вызовы wifi_log() - безусловные. А их там миллион. На каждый пакет, на каждый буффер, на каждый чих. Это адский оверхед. Понятно теперь, почему ЕСП32 не может выжать максимум из своего WiFi - код так написан. В добавок там один глобальный лок на ВСЕ операции. На медленные, на быстрые, на какие попало.

Какая неожиданная жесть.

Зато глобальных переменных миллион. Все, как мы любим. (у глобальных переменных остается их имя, и это удобно + дает кое-какую информацию о назначении переменной)

Такое происходит при коммутации индуктивной нагрузки очень часто. Можно поставить часы и производить перезагрузку, например каждые 2-3 часа. Хорошо что ESP грузится за секунды в сеть.

Как-то похоже на борьбу с ветряными мельницами. Вроде ж, ещё древние говорили: Sublata causa tollitur effectus

Еще интересная находка. Espressif или забыли, или умышленно оставили кое-какой код, который они использовали для тестирования своего железа. И там прям вообще удобно - минималистичный код, который тестирует RF часть. Например, там есть такое:

void esp_tx_func(void *param_1,uint32_t param_2)

{
  if (fcc_mode_sel) {
    wifitxout_func();
    return;
  }
  esp_tx_func_org(param_1,param_2);
  return;
}

Переменная fcc_mode_sel всегда установлена в true при обычной работе. Но если ее установить в false, то можно играться с параметрами сигнала. В частности, в коде теста радиочасти, они играются с передачей тона (какого-то) и мощности сигнала (выставляют в максимум) . Какой там реальный максимум (в документации максимум - 20мват) - непонятно.

Много и опечаток: названия вроде enable_debuge(bool en) или вот такое:

Знаете чо?

Нашел еще несколько бесплатных таймстампов (тикают всегда), правда, 32 бит. Но это не интересно. Интересно то, что в их ROM/Binary blobs зашит TEST SUITE для радиочасти WiFi и BT. Обычно так делают все вендоры - это требуется для прохождения сертификации - посылать чистый синус и измерять гармоники, мощность, то-сё.

И кажется (я уверен, но надо проверять) я нашел как этот режим включать и выключать. И даже менять частоту, правда, непонятно, какими шагами она меняется. Пока непонятно.

В принципе, ятобы включить этот режим, нужно записать 4 константы в 4 регистра. Правда, это билет в один конец, WiFi после этого работать как WiFi не будет. Зато мы получаем качественный, можно сказать, лабораторный генератор синуса на 2.4 ггц. Который, между прочим, прошел сертификацию FCC. Для РФ это не важно, а в других странах - еще как.

Иначе не продать железку.

Как только проверю и увижу своими глазами сигнала - запощу тут где-нибудь на форуме, как это сделать. Но пока у меня нечем смотреть сигналы на 2.4 ГГц.

Оказалось, что Espressif либо забыл, либо намеренно оставил код ATE (Automated Test Equipment) - код для тестирования WiFi и BT (на заводе и\или на сертификации). Там много интересного нашлось. Буду потихоньку выкладывать.

1 лайк