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

Баги и недосмотры в 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 вставить может...
 
Последнее редактирование:
Сверху Снизу