Баги и недосмотры в sdk от espressif

pvvx

Активный участник сообщества
Продолжим про ошибки.
Есть такая переменная/константа, в Lwip :
MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections.
Назначена в lwipopts.h (файл конфигурации для Lwip):
#define MEMP_NUM_TCP_PCB (*(volatile uint32*)0x600011FC)
Устанавливается процедурой espconn_tcp_set_max_con(n). Можно поставить больше 5-ти, но тогда espconnбудет падать. Об этом уже писал (espconn использует ограниченный до 5 соединений массив в памяти и не проверяет выход за его пределы) и в выложенных мной исходниках библиотек уже исправлено – поставил ограничение до 5 (базовая espconn.c строка где-то 308). В данном случае, если это значение снесет в ноль или более 5, то это не лечиться перепрошивкой (у меня не получилось, но сильно не старался). Она глубоко запоминается где-то в нутре, и восстановить базовое значение можно только собрав свои исходники с вызовом espconn_tcp_set_max_con(5).
 

CHERTS

Moderator
Команда форума
Вам про это и написал - если меняете что-то в одной из либов, то другие не собираются (учитесь писать маке).
Зачем? если есть autoconf, automake для генерации Makefile на основе более простых скриптов (configure.ac) без мудреностей. В моем configure.ac отсилы 10 строк для генерации Makefile и сборки liblwip, в Вашем Makefile более 150 строк, что проще сделать, написать 10 или 150 строк?

Видно что с MCU не имели дело - там не бывает миллионов либов.
Здесь Вы правы, в микроконтроллерах я полный нуль, не работал с ними, ну всякие Arduino не в счет.
 

CHERTS

Moderator
Команда форума
pvvx я тут сравнил твои исходники lwip с теми что в IoT_Demo, и они сильно различаются
 

pvvx

Активный участник сообщества
pvvx я тут сравнил твои исходники lwip с теми что в IoT_Demo, и они сильно различаются
Возможно там вместо таб - пробелы. Использовал разные редакторы и пытался отладить с разными затычками - от этого там может просто сдвинуто что... Но если хотите поправить с чистого листа - ищите там PV` . Все изменения помечены и находятся в двух файлах.
Да - ещё: исходники используют user_config.h, а он может быть разный... и даже в нем, базовом, от "производителя" :) есть ошибки. Берется он от Iot_demo. Скорректируете, если что, сами...

Внешние Define повязаны много где, но ваша среда (Eclipse) их не распознает (ей никто об этом не сообщал) и у неё желтеют некоторые зависимости…

-DLWIP_OPEN_SRC встречается много где lwip и в esp_iot_sdk\include\user_interface.h

-DPBUF_RSV_FOR_WLAN IoT_Demo\lwip\core\pbuf.c

-DEBUF_LWIP IoT_Demo\include\lwip\pbuf.h и т.д.
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
Возможно там вместо таб - пробелы. Использовал разные редакторы и пытался отладить с разными затычками - от этого там может просто сдвинуто что... Но если хотите поправить с чистого листа - ищите там PV` . Все изменения помечены и находятся в двух файлах.
Да - ещё: исходники используют user_config.h, а он может быть разный...
diff нам в помощь ;)
кое что не помечено, твоё?

файл espconn_tcp.c, функция espconn_tcp_accept
после строки LWIP_UNUSED_ARG(err);
добавлено if(system_get_free_heap_size()<-8192) return ERR_MEM;

файл espconn_tcp.c, функция espconn_client_err
после строки pcb = perr_cb->pcommon.pcb;
добавлено if(pcb == NULL) return;
 

pvvx

Активный участник сообщества
if(system_get_free_heap_size()<-8192) return ERR_MEM; надо, а то падает при заполнении heap.
счас другое посмотрю..
"добавлено if(pcb == NULL) return;" не надо, но и не мешает - не вставляй в итог.
Дело в том, что после закрытия соединения lwip, при случайном распределении указателей pcb уже на другое соединение по тому же адресу, а это часто, espconn при ещё других обстоятельствах, повесит на на это "чужое соединение" эту функцию. Ну неисправима её логика... Всё работает на вероятностях, что ничего за время безделья espconn в стеке tcp не произошло...
 
Последнее редактирование:

pvvx

Активный участник сообщества
Пока испытываю на глюки НТTP сервер без espconn, на lwip-е. Всё хорошо - держит больше 10 одновременных запросов файликов, но не падает и не глючит. Картинка - https://yadi.sk/i/1u_jEjDNdQJ9m . Там все броузеры на максимальной скорости запрашивают скриптовый файл (xml) у HTTP на ESP8266. Прием/передача длинных файлов - к 500кБайт в сек, мелких дольше - там на открыть/закрыть большие издержки...
А прием, обработка данных и передача с одинаковым трафиком длинных файлов (в десятки мегобайт) - очень медленно идет. Сказываются задержки по всем линиям и в нутре ESP8266, да короткий стек. Итог - 20 кило в сек, не больше... Забудьте про espconn на tcp... До той загрузки она уже десятки раз бы упала...
 

CHERTS

Moderator
Команда форума
Пока испытываю на глюки НТTP сервер без espconn, на lwip-е. Всё хорошо - держит больше 10 одновременных запросов файликов, но не падает и не глючит. Картинка - https://yadi.sk/i/1u_jEjDNdQJ9m . Там все броузеры на максимальной скорости запрашивают скриптовый файл (xml) у HTTP на ESP8266. Прием/передача длинных файлов - к 500кБайт в сек, мелких дольше - там на открыть/закрыть большие издержки...
А прием, обработка данных и передача с одинаковым трафиком длинных файлов (в десятки мегобайт) - очень медленно идет. Сказываются задержки по всем линиям и в нутре ESP8266, да короткий стек. Итог - 20 кило в сек, не больше...
Отличный результат pvvx :) молодец
Десятки мегабайт и не нужно наверно, 500 кб думаю предел потребности забора с ESP по HTTP.

Забудьте про espconn на tcp... До той загрузки она уже десятки раз бы упала...
А может реалиовать некий аналог espconn, но только сделать все по нормальному? Напрямую работать с lwip конечно хорошо и правильно, но не все в этом специалисты, многим нужен упрощенный вариант работы со стеком tcp.
 
  • Like
Реакции: pvvx

pvvx

Активный участник сообщества
Ну делаю я. Не всё сразу. 512 кб - это сама Flash :) Большинство файлов сжато pkzip. Скриптовые - нет. Они шинкуются при передаче - размер то итоговый не известен. Станицы не показываю пока (их там много) т.к. дизайна никакого. Все известные переменные ESP8266 уже может отдать в виде xml и текстовой вставкой в файл... Но работы над этим бардаком ещё много...
Насчет напрямую без espconn - я пример вам давал. Там ничего сложного и отличия от espconn всего одно - нет глюков.
 

pvvx

Активный участник сообщества
Может для тестирования выпустить в Инет и опубликовать IP например здесь и на esp8266.com?
Это уже было, но без публикации IP. И на сервере много страниц с парольным доступом для установок. Оставлял на сутки по IP, куда падают всякие запросы из инет. Живет. В ручную, зная глюки Lwip и прочих совокупностей тестировать проще и быстрее. Проблемы для http сервера и так известны и объявлены:
1) Ограничение связанное с заполнением памяти TIME_WAIT pcb от закрытых соединений на 60 сек, в основном при обращении к серверу через proxy. Покси не любят закрывать первыми соединение, что не является стандартом в системе http сервер-клиент. Делают это они чтобы избежать собственное замусоривание памяти отложенными TIME_WAIT pcb от закрытых соединений на 60 сек.
2) Размер Flash ESP8266 для поддержки нормальных страниц и разных броузеров мал. Сейчас ограничение набора файловых ресурсов встроенного веб составляет к 200 кбайтам.
Надо создать тему на тему "Вопросы и ответы по построению Http сервера на ESP8266"...
SDK version:0.9.3
Check Settings...Ok.
UDP Test port 1025 init
TCP Server init on port 80 - Ok
Max connection 99, time waits 1 & 3, min heap size 16384
TCP Server start - Ok
TCP Server init on port 8080 - Ok
Max connection 3, time waits 30 & 30, min heap size 16384
TCP Server start - Ok
Всё по взрослому. :) Не удалось реализовать поддержку "Connection: keep-alive" - слишком мало памяти. Передача множественных запросов в одном и том же соединении связана уже со стеком этим запросов - вот их некуда складывать.
418, HTTP_RESP_FLG_END | HTTP_RESP_FLG_FINDFILE,
"I'm a teapot",
"418: Out of Coffee\r\n"
Это ^ сервер тоже поддерживает. :) И "Как было отмечено Стефаном Мёбиусом, предложенная спецификация протокола HTCPCP имеет тот недостаток, что не предусматривает кода ошибки «Out of Coffee» для случая, когда кофе в кофеварке закончился." у меня уже поддерживается. :)
Это уже не первая реализация мной простого http. Ранее, на MCU с 8 килобайтами памяти, несколько лет назад, были успешно построены http серверы c файловой системой на flash в дцать мегобайт с накоплением годовой статистики и графическим отображением её и они дос их пор работают в пром сетях :). Безусловно там ограничений было больше, чем у ESP8266 и сейчас хочу тоже исчерпать весь ресурс ESP8266. Т.е. пока не реализую свои задумки, исходников не будет. От них ныне мало толку – они ежедневно меняются и носят отладочный характер.



Пока можно побаловаться с этим Франкенштейном
Introducing esp-httpd: webserver on an ESP8266.
 
Последнее редактирование:

pvvx

Активный участник сообщества
В новом SDK 0.9.4 все описанные тут ранее ошибки и недочеты присутствуют. До писателей SDK начало доходить, что espconn c tcp имеет массу ошибок и обещают исправить.
Внедрили глупость espconn_option и ещё увеличили затраты памяти описателей на соединение. Ей они пытаются бороться с известной TIME_WAIT на 60 сек :)
Игра в заплатки у писателей из Espressif ради поддержки неверно выбранной концепции работы со стеком tcp набирает обороты. Будет интересно посмотреть, сколько это родит новых надпротоколов :)

Ждем SDK 0.9.5 :)
А пока, чтобы этим хоть как-то пользоваться, корректированная библиотека liblwip.a для SDK 0.9.4 v1 https://yadi.sk/d/jFNo7bYYdW6dy

Копируем liblwip_cor.a в lib SDK и меняем в маке lwip на lwip_cor.
 
Последнее редактирование:

clinkme

Member
Что-то новая версия SDK, даже с твоими правками, совсем нерабочая.
У меня в коде есть такая последовательность:
espconn_sent(sbuf->conn, &seq, 1);
espconn_sent(sbuf->conn, (uint8_t *)&r, sizeof(reply_t));

Размер первого сообщения - 1 байт, второго - 4 байта.
На новом SDK я вижу на приемной стороне только один байт - от первого вызова _sent().
Второй вызов пропадает неизвестно куда. На предыдущих SDK, начиная от 0.9.2, все работало.
 

pvvx

Активный участник сообщества
Что-то новая версия SDK, даже с твоими правками, совсем нерабочая.
У меня в коде есть такая последовательность:
espconn_sent(sbuf->conn, &seq, 1);
espconn_sent(sbuf->conn, (uint8_t *)&r, sizeof(reply_t));

Размер первого сообщения - 1 байт, второго - 4 байта.
На новом SDK я вижу на приемной стороне только один байт - от первого вызова _sent().
Второй вызов пропадает неизвестно куда. На предыдущих SDK, начиная от 0.9.2, все работало.
sint8 espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length);
Пропущено указание на структуру соединения?
А - не! До передачи буфера, вызова sent_cb, не стоит вызывать повторно espconn_sent().

Алго такое:
Создаете в памяти буфер (хоть 30 килобайт) и заливаете в него данные. espconn_sent передаете указатель на буфер и размер блока. Сидите и ждете вызова sent_cb. По нему освобождаете буфер. Если до этого произошёл дисконнект или ещё чаго, в неисправленной версии вы теряете память. Освобождайте буфер по recon_cb или discon_cb.
Детсадом (https://ru.wikipedia.org/wiki/Алгоритм_Нейгла) никто не болеет
Lwip:
tcp_nagle_enable ( struct tcp_pcb * aPcb ); // enable the nagle algorithm
tcp_nagle_disable ( struct tcp_pcb * aPcb ); // disable the nagle algorithm
tcp_nagle_disabled ( struct tcp_pcb * aPcb ); // return true if the algorithm is not enabled
Но данные в pcb espconn передаются без буферизации - tcp_write(struct tcp_pcb * pcb, void * dataptr, u16_t len, u8_t apiflags) см http://lwip.wikia.com/wiki/Raw/TCP
Из этого следует, что пока данные не отосланы, освобождать буфер с ними нельзя.
По этой причине, меня очень веселят такие писаны у многих:
int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) {
int len;
char buff[1024];
….
if (len>0) espconn_sent(connData->conn, (uint8 *)buff, len);
….
} :) это из http://www.esp8266.com/viewtopic.php?f=6&t=376 :)
 
Последнее редактирование:

pvvx

Активный участник сообщества
Кто объяснит, зачем открыт в dns порт 4096 ?
Смотрю список открытых портов:
UDP pcbs:
flg:00 0.0.0.0:67 0.0.0.0:0 recv:40258fcc (Это DHCP)
flg:00 192.168.4.1:1025 192.168.4.2:1026 recv:4025aa64 (Этот порт я открыл и по нему идет запрос и ответ этой информации)
flg:00 0.0.0.0:4096 0.0.0.0:0 recv:40259600 (это dns_recv(…) из libs/lwip/core/dns.c)
Но зачем он открыт? Кого он там ждет?
 

pvvx

Активный участник сообщества
Новые фичи в SDK 0.9.4 от Espressif :D
В esp_iot_sdk_v0.9.4/include/user_interface.h объявлено:
enum dhcp_status wifi_softap_dhcps_status(void);
enum dhcp_status wifi_station_dhcpc_status(void);
Но этих функций нет в библиотеках (либах)! Опять подсунули что-то кривое. o_O

Решение у меня пока такое - их надо заменить на:
extern uint8 dhcps_flag;
extern uint8 dhcpc_flag;
#define wifi_softap_dhcps_status() dhcps_flag
#define wifi_station_dhcpc_status() dhcpc_flag
А ту ерунду от Espressif пока не исправили закоментить. :)
 
Последнее редактирование:

clinkme

Member
Из этого следует, что пока данные не отосланы, освобождать буфер с ними нельзя.
Да, у меня эти данные действительно лежали в стеке и была вероятность, что espconn_sent() не успевала
передать их, а стек уже был разрушен.
Ладно, перенес их в глобальную структуру. Все равно в 0.9.4 данные отправляет только первый вызов
espconn_sent()!
Кстати, скомпилировал свой код с твоим Tcp_serv_demo_v0.1 с минимальными изменениями.
Работает! И в 0.9.3, и в 0.9.4.
Нет желания развить это дело, чтобы полностью отказаться от espconn?
 

pvvx

Активный участник сообщества
Нет желания развить это дело, чтобы полностью отказаться от espconn?
Я давно отказался от espconn. И развитие тоже показывал, но пишу ещё и исходников пока не будет...

Причина в том, что не желаю, чтоб использовали в коммерческих целях.

Для этого сначала надо исправить все ошибки и раздать всем рекомендации и куски, чтоб сами всё сделали. Потом, когда разного кода от разного народу будет навалом, тогда и буду выкладывать свои исходники. :)
Пока дает и управляет системной инфой:
<response>
<name>Web on ESP8266!</name>
<gpio>-536674255</gpio>
<gpio0>1</gpio0>
<gpio1>0</gpio1>
<gpio2>0</gpio2>
<gpio3>0</gpio3>
<gpio4>1</gpio4>
<gpio5>1</gpio5>
<gpio6>0</gpio6>
<gpio7>0</gpio7>
<gpio8>0</gpio8>
<gpio9>0</gpio9>
<gpio10>0</gpio10>
<gpio11>0</gpio11>
<gpio12>0</gpio12>
<gpio13>0</gpio13>
<gpio14>0</gpio14>
<gpio15>0</gpio15>
<gpio16>1</gpio16>
<gpio17>1</gpio17>
<gpio18>0</gpio18>
<gpio19>0</gpio19>
<gpio20>0</gpio20>
<gpio21>0</gpio21>
<gpio22>0</gpio22>
<gpio23>0</gpio23>
<gpio24>0</gpio24>
<gpio25>0</gpio25>
<gpio26>0</gpio26>
<gpio27>0</gpio27>
<gpio28>0</gpio28>
<gpio29>1</gpio29>
<gpio30>1</gpio30>
<gpio31>1</gpio31>
<sys>
<chipid>0099acf1</chipid>
<flashid>001340c8</flashid>
<sdkver>0.9.4</sdkver>
<webver>0.1.0</webver>
<adc>69</adc>
<time>115106561</time>
<espconn_tcp_get_max_con>5</espconn_tcp_get_max_con>
<rtctime>17721159</rtctime>
<sleeptype>2</sleeptype>
<heap>30976</heap>
</sys>
<wifi>
<connectstatus>0</connectstatus>
<autoconnect>0</autoconnect>
<mode>3</mode>
<id>0</id>
<phy>3</phy>
<chl>1</chl>
<ap>
<ssid>ESP8266</ssid>
<password>0123456789</password>
<channel>1</channel>
<authmode>0</authmode>
<ssid_hidden>0</ssid_hidden>
<max_connection>4</max_connection>
<ip>192.168.4.1</ip>
<gw>192.168.4.1</gw>
<netmask>255.255.255.0</netmask>
<mac>1a:fe:34:99:ac:f1</mac>
<dncp>1</dncp>
</ap>
<st>
<ssid>TESTAP</ssid>
<password>0123456789</password>
<bssid>ff:ff:ff:ff:ff:ff</bssid>
<setbssid>0</setbssid>
<ip>0.0.0.0</ip>
<gw>0.0.0.0</gw>
<netmask>0.0.0.0</netmask>
<mac>18:fe:34:99:ac:f1</mac>
<dncp>1</dncp>
</st>
</wifi>
</response>
Это тестовая подборка в виде xml, но любую и в htm вставить может...
 
Последнее редактирование:
Сверху Снизу