• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

'Реверс' SDK Espressif и ROM-BIOS для создания открытого SDK.

pvvx

Активный участник сообщества
Я думаю было бы было бы интересно сочетание http://richard.burtons.org/2015/05/17/decompiling-the-esp8266-boot-loader-v1-3b3/ с OpenSDK.
Там всего загрузчик, без какой-либо операционки и включения "кеширования" flash. Т.е. из него не вызвать процедуры из flash и его задача всего загрузка других кусков, да и он при этом занимает память IRAM. Могли бы его перенести и в другую область, которая затирается далее нужным кодом. Ведь он не нужен после загрузки. Короче это очередной китай-бред, связанный с тем, что у них уже ничего не лезет в 512к flash и для их системы обновления по сети.
КОИ8 тут вряд ли поможет. Мне кажется Вы зря не хотите переходить на UTF8, сейчас это повсеместный стандарт. Да и для международного проекта самое правильное решение :)
Да я ошибся. UTF8 конечно. Не важно какая локальная кодировка - git при передаче/приеме всё равно перекодирует, но надо правильно задать эти параметры и знать какие и где... Пока не заботился и сильно не копал это дело...
 
Последнее редактирование:

anakod

Moderator
Команда форума
Там всего загрузчик, без какой-либо операционки и включения "кеширования" flash. Т.е. из него не вызвать процедуры из flash и его задача всего загрузка других кусков, да и он при этом занимает память IRAM. Могли бы его перенести и в другую область, которая затирается далее нужным кодом. Ведь он не нужен после загрузки. Короче это очередной китай-бред, связанный с тем, что у них уже ничего не лезет в 512к flash и для их системы обновления по сети.
Не думаю, во-первых это вроде энтузиастами сделано а не Espressif, а во-вторых оно как раз заточено под задачу произвольного хранения и загрузки неограниченного количества образов прошивок (в пределах мегабайта флешки). Про память - согласен, если тратит лишнее это не гуд, ее и так мало.

UPD А как сделать чтобы память использовалась повторно?
 

pvvx

Активный участник сообщества
Не думаю, во-первых это вроде энтузиастами сделано а не Espressif, а во-вторых оно как раз заточено под задачу произвольного хранения и загрузки неограниченного количества образов прошивок (в пределах мегабайта флешки).
Вот и говорю - у него совершенно другая задача и это не самостоятельная примочка, а кусок созданный исключительно для китай-SDK :)
А собираемое "творение" - это полноценная система. С ней можете странслировать и Дурино без WiFi. Такая система сделана для того, чтобы иметь максимум памяти и максимум производительности + минимум потребления и/или использовать модуль ESP8266 как обычный MCU без WiFi. Подгрузка китай-SDK c WiFi для передачи накопленных данных вписывается отдельным блоком, который запускается когда данные уже обработаны/готовы и положены в RTC_RAM или flash.
Сейчас в данной системе не хватает только правильного sleep, с засыпанием CPU и т.д. (потребление модулем на уровне 2mA). Он представлен (все функции есть) в ROM-BIOS. Время его отработки от пары ms до ... Очень необходимая фича для ожидания готовности внешних датчиков. Необходимо дописать "сервис" обращения к ней (кто и почему вызывает просыпание, сколько предел по времени и т.д.) и ввести коррекции (она кривовата). Всё остальное, кроме специфических драйверов для внешних устройств уже есть в данном "OpenSDKnoWiFi"
Этот sleep режим уже проверен и часть показана в блоке Код (C) dtm_params_init(NULL, NULL); dtm_set_params(0,3000*26/40,0,0,0); rtc_enter_sleep();
Есть ещё второй режим sleep специфичный для самого CPU, так-же с задаваемыми источниками "просыпания" и временем в тактах CPU + callback-и. Так-же уже реализован в ROM-BIOS в ets_run(), но пока используется на 1%. Он требует немного специфичной политики организации работы с прерываниями таймеров и т.д. А в текущих Дуринах и прочих ПО это не используется и игнорируется - там у писателей главное побольше набить галочек и напихать побольше "портирований" всего и вся... :)
PS: Я всегда за разнообразие, а не унификацию – “сделать всё серым”. Природа любит разнообразие и ничего лишнего и каждой фиговинке свои цели и программа… :) После "Дурин" большинство уже ничего не может сделать самостоятельно. И их много развелось - баланс нарушен :)
 
Последнее редактирование:

pvvx

Активный участник сообщества
Кто может объяснить, почему в RTOS библиотеках включены все дубли кодов из ROM-BIOS? Это сделано чтобы неиспользуемого коду во flash было во много раз больше? (Китай-програмерам платят за каждую строчку кода, даже если он не нужен? :))
https://github.com/espressif/esp_iot_rtos_sdk/tree/master/lib
 

anakod

Moderator
Команда форума
pvvx, мы же с Вами как раз сегодня про оптимизацию и дублирование разговаривали :) Вот китайцы молодцы, никогда не забывают скописатить код, даже если он их собственный :D

Касательно RTOS: насколько он отличается, что там по DHCP (и можно ли использовать обычный)? Давно подумывал на него перейти.
 

pvvx

Активный участник сообщества
pvvx, мы же с Вами как раз сегодня про оптимизацию и дублирование разговаривали :)
Дык уже проросло http://www.esp8266.com/viewtopic.php?t=3420&p=19449#p19444

Касательно RTOS: насколько он отличается, что там по DHCP (и можно ли использовать обычный)? Давно подумывал на него перейти.
Там старая версия без излишков, но с дублями от первых либ v5 для WiFi (она полностью в ROM-BIOS, а SDK использует v6)
Пример, как входят дубли в те либы:
phy_chip_v5_ana_romfunc.o
phy_chip_v6_ana.o
phy_chip_v5_cal_romfunc.o
phy_chip_v6_cal.o
В v6 изменено до десяти функций. Список измененных уже приводился Код (Text).
У измененных название начинается с "ram_...", а от v5 в ROM-BIOS = "rom_..."
Касательно RTOS: насколько он отличается, что там по DHCP (и можно ли использовать обычный)? Давно подумывал на него перейти.
Используется DHCP из LwIP. И в SDK аналогично. Для ST - собственный-китайский :) В новом SDK 1.1.0 к ним подвязаны "события" типа GOT_IP... Это единственное правильное решение в их разработке, но сделано было криво...
Open mdns адаптировать некогда. Китайцы какую-то open версию стырили и вставили.
То, что лежит тут https://github.com/espressif/esp_iot_rtos_sdk/tree/master/third_party - это просто для приколу :)
Процедуры ROM-BIOS и остальные либы SDK не могут работать с мультизадачкой. Это в них никак не предусмотрено и по этому про RTOS можно забыть, пока не напишите всё сами.

Да, ещё отличие библиотек в RTOS от SDK1.1.0 в том, что китайцам пришлось "пойти на жертвы" - они выкинули часть неиспользуемых процедур из библиотек в SDK1.1.0, т.к. это уже никуда не лезло :)
 
Последнее редактирование:

JustACat

Moderator
Команда форума
Не работает только отображение в браузере.
Не хочется вас наставлять, но, вот как раз поэтому, в основном, и переходят все постепенно на UTF. Все же кодировки вроде 1251 или KOI себя изживают. И их использование только порождает в итоге проблемы.
Взять для примера хотя б Pebble - как они лоханулись, что в свой первый пебл не внедрили сразу юникод?.. Потом допиливали, мучились, не влезало. А заложили бы сразу - и проблемы бы не было вовсе.
Какой сейчас выигрыш от старых кодировок? Только размер файла разве что?..
В общем, не мне вас, @pvvx, учить и наставлять, конечно. Но все же хотелось бы, чтобы и вы перешли на светлую сторону силы UTF ^_^"
Китай-програмерам платят за каждую строчку кода, даже если он не нужен?
А мож правда так? Это даже ведь имеет название "Индусский код".
 

pvvx

Активный участник сообщества
JustACat - вопрос в том, что надо указать в TortoiseGit 1.8.14.0, чтобы он нормально перекодировал любой формат.
А расширение текстов и прочего в несколько раз по объему меня не устраивает. Пусть это будет на github, а у себя я буду использовать то, что совместимо с используемым мной ПО, пока не напишут замену с полной поддержкой UTF. Но этого пока не видать, т.к. причина не в том, а в том что везде насаждается английский (диалект США) язык. А от языка зависит многое...
Писатели из США не утруждают себя поддержкой других языков, а я должен? :)
 

pvvx

Активный участник сообщества
Проверил sleep в ROM-BIOS, который работает в est_run() без перезагрузки и с назначением события просыпания. (est_run() - это процедура исполняется всегда и в китай-SDK, в ней цикл с ожиданием прерываний)
Код:
Test 'SDK no WiFi'
Heap size:    81848 bytes
Bss size:    40 bytes
Stack pointer:    0x3fffffb0
ets_delay_us(1000) dt=1000
ets_delay_us(10000) dt=10001
Test sleep (low power) 1000 ms, 7 cycles
go ets_run()
Test cb1, t=30907
Test cb2, t=31888, dt=981
Test cb1, t=33391
Test cb2, t=34340, dt=949
Test cb1, t=35843
Test cb2, t=36792, dt=949
Test cb1, t=38292
Test cb2, t=39239, dt=947
Test cb1, t=40744
Test cb2, t=41692, dt=948
Test cb1, t=43196
Test cb2, t=44143, dt=947
Test cb1, t=45647
Test cb2, t=46593, dt=946
Test cb1, t=48097
Test cb2, t=49043, dt=946
Т.к. sleep отключает всё, то приходится восстанавливать PLL после выхода к кварцу на 26MHz...
Придется адаптировать/переписывать для OpenSDK, т.к. там назначается на событие просыпания всегда одна нога - GPIO2 и не правильно выставляется предельное время sleep в RTC (всё из-за кварца на 26MHz вместо 40MHz).
 

anakod

Moderator
Команда форума
То что сбивается это наверно достаточно закономерно, т.к. просыпание после deep sleep это фактически старт заново (с нуля). Или я ошибаюсь?
 

pvvx

Активный участник сообщества
То что сбивается это наверно достаточно закономерно, т.к. просыпание после deep sleep это фактически старт заново (с нуля). Или я ошибаюсь?
deep sleep написан и работает (см. sys_deep_sleep()).
А sleep - это выключение CPU и его потрахов (но не всех - RTC и другие блоки работают) на ходу. CPU останавливается, а после события продолжает работу с места "останова". Но и при этом почему-то его PLL сбита. Т.е. он продолжает работу с дефолтными установками и требует их восстановления.
Режим sleep удобен тем, что просыпание более быстрое и ничего в памяти не сбито. Потребление в нем минимально (точно ещё не измерял). Время входа и выхода мало - ограничения только на время восстановления PLL и некоторых других аппаратных "опций". На просыпание, кроме ограничения ( время таймера на RTC вызывающего INT) назначается ещё любое событие - например перепад уровня на входной ножке. Он дает экономию питания при ожидании ответов с внешних устройств. Но для user-ов требуется написание простой системы назначения всего этого дела...
Т.к. часы (CLK) у RTC не на кварце, а на внутреннем RC генераторе, то он неточный (зависит от температруры и т.д) и требует калибровки (регистры калибровки описаны в xls с GPIO). Перед входом в sleep она и выполняется (требуется > 100 us). Но можно и без калибровки, если она произведена заранее или точность предельного времени нахождения в sleep не требуется. Точное ограничение ожидания события от датчика обычно не требуется, т.к. оно используется как авария = датчик умер и не хочет отвечать :)
----
Для deep_sleep (sleep через reset) есть ветка быстрого старта (возобновления) в ROM-BIOS, но её использовать сложно – требует определенного состояния выводов (как и при программировании), а так-же не хватает информации по чипу + потеря значений в памяти RTC из-за отсутствия подключенного внешнего источника питания к ноге VCC_RTC (ROM-BIOS анализирует при старте некоторые значения там и от них зависит “ветвь старта”).
 
Последнее редактирование:

pvvx

Активный участник сообщества
Обобщая о системах low_power на ESP8266:

На данном чипе мы имеем 3 системы low_power:

1) Deep_sleep – sleep до события срабатывания “будильника” в RTC, назначенного на ножку вывода и соединенного с reset. При использовании SDKnoWiFi возобновление после deep_sleep < 30 ms.

2) Sleep - sleep до события прерывания. Назначается прерывание по таймеру RTC. Всё остальное, кроме спец. прерываний по I/O вырубается. Выходом, продолжением исполнения кода CPU с места засыпания, является срабатывание прерывания или I/O или таймера RTC. При использовании SDKnoWiFi возобновление работы после sleep, с установкой PLL на 26MHz кварц < 150 us. Без, для прямого опроса датчика сразу - наносеки.

3) Спец команда CPU * ожидания прерывания (ROM:40000F65: "waiti 0"). Глушит только CPU. Потребление модулем < 2 mA. Имеет установку ограничения времени нахождения CPU в данном режиме в спец. регистре CPU и задается в тактах CPU. Стоит в цикле ets_run(), где вечно сидит процессор. В итоге любой лишний включенный timer_arm() или безграмотный user-цикл опроса чего-либо (как в "Дуринах", особо её драйверах) увеличивает потребление чипом.
Организуйте работу системы по событиям, по возможности без всяких delay( >1 ms) и длительных циклов опросов. По событию (CPU лучше включить на 180MHz), отработать и встать опять на "waiti" до следующего события. Если время ожидания и опрос позволяет использовать sleep или deep_sleep - то и использовать их. Тогда потребление будет минимальным.

*The WAITI (Wait for Interrupt) instruction, which is a part of the Interrupt Option, saves power by setting the current interrupt level, powering down the processor’s logic, and waiting for an interrupt.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Протестировал потребление оптимизированного sys_delay_us() в замену est_delay_us():
TstOpenSDKnoWiFi.gif
Код:
Test 'SDK no WiFi'
Heap size:    81848 bytes
Bss size:    40 bytes
Stack pointer:    0x3fffffa0
sys_delay_us(1000000), dt=1000004
sys_delay_us(900000), dt=899999
sys_delay_us(800000), dt=800000
sys_delay_us(700000), dt=699999
sys_delay_us(600000), dt=599999
sys_delay_us(500000), dt=499999
sys_delay_us(400000), dt=399999
sys_delay_us(300000), dt=300000
sys_delay_us(200000), dt=199999
sys_delay_us(100000), dt=100000
ets_delay_us(1000000) dt=500000
Test sleep (low power) 1000 ms, 7 cycles
go ets_run()
Test cb1, t=6063443
Test cb2, t=6065320, dt=1877
Test cb1, t=6068129
Test cb2, t=6069962, dt=1833
Test cb1, t=6072766
Test cb2, t=6074593, dt=1827
Test cb1, t=6077392
Test cb2, t=6079215, dt=1823
Test cb1, t=6082023
Test cb2, t=6083857, dt=1834
Test cb1, t=6086658
Test cb2, t=6088488, dt=1830
Test cb1, t=6091300
Test cb2, t=6093129, dt=1829
Test cb1, t=6095940
Test cb2, t=6097767, dt=1827
Модуль ESP-01 с горящим светодиодом, пуск с CH_PD.
Что-то надо ещё отключить в потрохах ESP8266, но пока не нашел как и что... :)
 
Последнее редактирование:

pvvx

Активный участник сообщества
Почуть-чуть проясняется с WiFi, хотя я этим не занимаюсь, рассчитывая на других :) Мне было многократно сказано, в переписке, что кто-то разгребает WiFi процедуры... но пока что-то не видно и не слышно.
В частности код ieee80211 китайцами "скопирован" из freebsd.
Это подтверждают и тут: http://bbs.espressif.com/viewtopic.php?f=7&p=2113#p2113
В итоге особых проблем с WiFi частью быть не должно. Разве что со спецификой, связанной c аппаратными фичами чипа.
----
Ещё пустили байку-слух, что выйдет новый чип ESP с большей памятью. Наверно настолько плохи дела у NodeMCU :)
Да и пока стало "легче жить" - все "телепузики" ушли на arduino :)
 
Последнее редактирование:

anakod

Moderator
Команда форума
and finally outputting the frame via ieee80211_mgmt_output which internally calls ieee80211_raw_output which in my opinion is replaced by ppTxPkt in ESP, so maybe the signature is similar.
Если так, то мне кажется можно взять одну эту функцию бинарником/асмом либо дизассемблировать, а все остальное накатить из оригинала с полными исходниками.
 

pvvx

Активный участник сообщества
Если так, то мне кажется можно взять одну эту функцию бинарником/асмом либо дизассемблировать, а все остальное накатить из оригинала с полными исходниками.
Да, но там, в оригинале, слишком много лишнего - ~60%. А разбираться с этим лень. Оригинал писало несколько человек и одному разгребать долго.
Первым делом надо тупо отсортировать, какие функции есть в SDK либе 80211, в каждом входящем obj.
Код:
libnet80211.a:ieee80211.o
libnet80211.a:ieee80211_action.o
libnet80211.a:ieee80211_crypto.o
libnet80211.a:ieee80211_crypto_ccmp.o
libnet80211.a:ieee80211_crypto_tkip.o
libnet80211.a:ieee80211_crypto_wep.o
libnet80211.a:ieee80211_ets.o
libnet80211.a:ieee80211_hostap.o
libnet80211.a:ieee80211_ht.o
libnet80211.a:ieee80211_hwmp.o
libnet80211.a:ieee80211_input.o
libnet80211.a:ieee80211_mesh.o
libnet80211.a:ieee80211_node.o
libnet80211.a:ieee80211_output.o
libnet80211.a:ieee80211_phy.o
libnet80211.a:ieee80211_power.o
libnet80211.a:ieee80211_proto.o
libnet80211.a:ieee80211_scan.o
libnet80211.a:ieee80211_sta.o
libnet80211.a:if_eagle.o
libnet80211.a:wl_chm.o
libnet80211.a:wl_cnx.o
Например так:
https://github.com/pvvx/esp8266web/blob/master/info/libs/net80211/ieee80211_output.h
Потом надо разгрести форматы запросов и удалить лишнее.
Затем уже уточненно сравнивать с дизасм, что там китайцы накрутили своего для связи с другими частями и т.д.
Потом, проанализировав итого, загрузив всё в голову, сесть на попу и переписать исходники из оригинала. :)
 
Последнее редактирование:

pvvx

Активный участник сообщества
Вот так делается сохранение всех и каждый раз измененных параметров WiFi в SDK:
Код:
void wifi_param_save_protect_with_check(uint16 startsector, int sectorsize, void *pdata, uint16 len)
{
    uint8 * pbuf = pvPortMalloc(len);
    int i;
    if(pbuf == NULL) return;
    do {
        spi_flash_erase_sector(startsector);
        spi_flash_write(startsector*sectorsize, pdata, len);
        spi_flash_read(startsector*sectorsize, pbuf, len);
        i = ets_memcmp(pdata, pbuf, len);
        if(i) {
            os_printf("[W]sec %x error\n", startsector);
        }
    } while(i != 0);
    vPortFree(pbuf);
}
Т.е. если сектор уже помирает, то оно будет писать "пока дым не пойдет". Китай поражают своим программированием... :)
При старте модуля (питание, reset, deep_sleep) обычно последний сектор flash стирается и переписывается 2 раза. При соединении к AP тоже стирается и переписывается :mad:
И делается это (тратится 4 килобайта) для сохранения всего двух контрольных сумм предыдущих 2-х секторов, в которых тоже стираются и переписываются данные до 888 байт...
Кроме этого в SDK 1.3.0 в некоторых случаях, в процедуре инициализации SDK, стирается и сектор перед сектором с блоком в 128 байт esp_init_data_default.bin (убивает SPIFFS в Дуринах :) ).
Код:
.irom0.text:40240533                 l32r            a2, a_flashchip
.irom0.text:40240536                 l32i            a2, a2, 0 ;получить адрес структуры flashchip
.irom0.text:40240539                 l32i            a14, a2, 0xC ; flashchip->sector_size (размер сектора = 4096 байт)
.irom0.text:4024053C                 l32i            a2, a2, 4 ; flashchip->chip_size (размер flash в байтах)
.irom0.text:4024053F                 mov.n           a3, a14
.irom0.text:40240541                 l32r            a0, a___udivsi3
.irom0.text:40240544                 callx0          a0 ; a2=a2/a3 =  делить размер flash в байтах на размер сектора
.irom0.text:40240547                 mov.n           a3, a14 ; flashchip->sector_size (размер сектора = 4096 байт)
.irom0.text:40240549                 l32i.n          a4, a1, 0x14 ; адрес блока полученного по pvPortZalloc(256)+0x80 ранее. Туда сохранен блок в 128 байт всех равных 0xFF из сектора с адресом end_flash-0x5000 (=0x7B000).
.irom0.text:4024054B                 addi            a2, a2, -5 ; end flash sectors - 5 !!! (0x7B000 !)
.irom0.text:4024054E                 movi            a5, 0x80 ; 128 байт
.irom0.text:40240551                 call0           wifi_param_save_protect_with_check
:eek:
Не читайте китайские доки о разметке их Flash с использованием последних 5-ти секторов - там про это ничего не сказано! :)

Итого на сохранение 888*2+128 байт китай-SDK расходует последние 16 ... , т.е 20 килобайт Flash. :)

И ошибки во всех версиях SDK в:
Код:
bool wifi_station_set_hostname(uint8 * name)
{
    if(name == NULL) return false;
    uint32 len = ets_strlen(name);
    if(len > 32) return false;
    uint32 opmode = wifi_get_opmode();
    if(opmode == 1 || opmode == 3) {
        default_hostname = false;
        if(hostname != NULL) {
            vPortFree(hostname);
            hostname = NULL;
        }
        hostname = pvPortMalloc(len);
        if(hostname == NULL) return false;
        struct netif * nif = eagle_lwip_getif(0);
        ets_strcpy(hostname, name); // пишется на 1 байт больше, чем было выделено по vPortFree(hostname) !!!
        if(nif != NULL) {
            nif->hostname = hostname;
        }
        return true;
    }
    return false;
}
 
Последнее редактирование:

pvvx

Активный участник сообщества
При старте (инициализации SDK) отрабатывает функция phy_gpio_cfg(), которая в качестве исходных опций использует esp_init_data_default.bin байты 50,51,52,53,54,64 и в зависимости от которых она меняет функции GPIO 0,1,2,3,13,14,16 и так-же “SDIO dataoutput is at negative edges (SDIO V1.1)”или “SDIO dataoutput is at positive edges (SDIO V2.0)“ (байт 50) и лезет в неописанные регистры контроллера SDIO (0x60000A00..0x60000Aff).

Кто копался с этим и может дополнить или уточнить детали с esp_init_data_default.bin и SDIO (0x60000A00..0x60000Aff)?
 

dronvolk

New member
Похоже тема заглохла... дайте хоть ссылки на описание ассемблера этого чуда в перьях. недавно прикупил себе парочку модулей (да повелся на отношение цена-возможности), а тут sdk наикривейший и нифига описания нет нормального по чипу. придется самому ковырять этот sdk вдруг что получится :D.
 

pvvx

Активный участник сообщества
Похоже тема заглохла... дайте хоть ссылки на описание ассемблера этого чуда в перьях. недавно прикупил себе парочку модулей (да повелся на отношение цена-возможности), а тут sdk наикривейший и нифига описания нет нормального по чипу. придется самому ковырять этот sdk вдруг что получится :D.
За данное время сменилось много версий SDK и всё что было надо - сделали. Если не знаете где и как взять дизасм, то и браться не стоит :) Берите IDA и вперед.
 
Сверху Снизу