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

pvvx

Активный участник сообщества
Основные баги от Espressif для SDK 0.9.3 в их отвратительном и лажевом espconn:

Кол-во одновременно открытых соединений можно изменить в espconn_tcp_set_max_con(x). Но espconn пользуется массивом из 5 структур remot_info premot[5], размещенной в постоянной памяти. Соответственно, при указании кол-ва соединений более 5 она испортит память за данным массивом структур :)

При закрытии tcpсоединения, espconn часто теряет событие disconnect. Тем самым, отведенные, и так по максимуму 5 соединений, заполняются и остаются занятыми. Получаем ошибку ESPCONN_CONN = - 11. Освобождение внутренних структур espconn у Espressif для занятых соединений сделано некорректно – лезут в Lwip по запомненному указателю на когда-то живую структуру pcb и что-то там сравнивают :). Но структура уже исключена из списка активных и неактивных соединений в Lwip-е. Память может быть затерта уже другими процедурами, а может и нет. В итоге, от значений там, зависит освободит или нет espconn занятый блок на соединение :) Дополнительно это дает путаницу номерков соединений в ATпрошивке :)
Только эти баги уже напрочь закрывают возможность пользоваться любыми интернет соединениями с ESP8266 на любых прошивках, основанных на текущем SDK, без грубых 'хаков'. А багов ещё очень много и не описываю, пока не конкретизированы их конкретные источники. Т.е. писать 'надстройки' на текущий SDK преждевременно.
 
Последнее редактирование:

Andy Korg

Moderator
Команда форума
Жалко конечно, что такие баги. Но видно кто-то обходит их. Вот эта прошивка http://git.spritesserver.nl/esphttpd.git/ вроде как довольно стабильно работает. Мне правда так и не удалось ее скомпилировать.
 

pvvx

Активный участник сообщества
В той “прошивке” https://github.com/mziwisky/esp8266-dev те-же баги. Она работает с espconn.

Конкретно:
espconn_server_close ставит таймер на espconn_sclose_cb:

os_timer_setfn(&psclose->pcommon.ptimer, espconn_sclose_cb, psclose);

os_timer_arm(&psclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0);

espconn_sclose_cb, спустя время таймера, смотрит состояние у передаваемой структуры, в которой указана старая ссылка на pcb в стеке Lwip-а. К этому моменту данная pcb может быть уже исключена из списка и этот кусок памяти освобожден lwip-ом. По состоянию байт в данном куске памяти espconn_sclose_cb снова ставит таймер и так продолжается, пока в данном куске памяти не выпадут подходящие значения для espconn_sclose_cb (некий байт там не станет равен значению CLOSED или TIME_WAIT) :) Когда нибудь ей повезет и тогда будет вызван calback disconnect-а пользователя. А пока не везет, занят таймер и disconnect-а соединения нет. А “везет” ей тогда, когда в данную область памяти Lwip распределит другой pcb, от другого соединения, и у него будет состояние CLOSED или TIME_WAIT… Тогда disconnect для “потерянного соединения” завершится. Но если этот кусок памяти Heap занял кто-то другой и распределение памяти сдвинулось, то по вероятности 2 к 256, зависящей от ожидаемого там espconn_sclose_cb значения байта завершится disconnect для “потерянного соединения” :)
Это ошибка в алгоритме ecpconn и патчем не лечится. Обходится путем использования Lwip напрямую, без espconn от "чудаков" из Espressif.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Есть ещё такая беда. При приеме через соединение tcp, установленное в espconn, нет возможности управления скоростью входного потока. Это сказывается всегда, когда имеем входной поток tcp более чем успеваем обработать. Пример – надо принять файл длиной более имеющегося буфера в памяти Heap. Пусть для записи во flash или передачи по UART. Функция работы со стеком espconn tcp будет выдавать блоки со скоростью ограниченной только соединением wifi (это более мегобайта в секунду). В итоге имеем или переполнение памяти и потерю информации - придется отбрасывать, то что не влезает и повторять всё с начала. На tcp стеке это решается через управление окном приема WIN в TCP (в Lwip это есть), но espconn не предоставляет таких средств управления и такие задачи на ней не решить. Только если использовать нестандартные надвески над протоколами – на передающей стороне резать передаваемую информацию на куски и следить, как тама модуль с espconn, проглотил прошлый кусок и уже можно давать следующий (?) :)

----------
С lwip это организуется так:

Ставим throttle_data_reception = true.

После этого по tcp будет принято в организованный буфер RAM до WIN + пара пакетов cдлиной MSS. Окно WIN tcp в SDK с Lwip1.4.0 у ESP8266 = 4*MSS, MSS=1460 байт. Следовательно, буфер c резервом, надо на 6*MSS = 8760 байт.

В процедуре приема:

err_t callback_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)

{

….

if (throttle_data_reception) unrecved_bytes += p->tot_len;

else tcp_recved(pcb, p->tot_len); // сообщает стеку, что можно посылать ACK и принимать новые данные.

….

}

Когда данные обработаны, вызываем tcp_recved(pcb, unrecved_bytes), чем позволяем стеку и всем кто там за ним, передачу нам следующих байт. Таким образом мы можем принять и обработать бесконечный поток с ограниченной скоростью приема, без потерь ...
----------

Как заключение – имеющийся SDK рассчитан на работу по tcp с предельными сообщениями до пары килобайт и обработке одного активного соединения (что лезет в организованный буфер в RAM– это до 8 кбайт, с учетом распределения RAM для работы остального ПО).
Остальные (все!) писанные на сегодня надстройки на SDK от Espressif, использующие espconn, имеют описанные ограничения и баги. :)
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
Судя по всему стек lwip в SDK не самый свежий, в офф. репозитарии активно исправляются баги http://git.savannah.gnu.org/cgit/lwip.git

pvvx а можешь привести простенький пример нативной рабоыт с lwip, например на примере организации tcp-сервера или клиента?
 

pvvx

Активный участник сообщества
Что-то не видать тут никакого “сообщества” – никто не делиться информацией по SDK... :)
Не вижу смысла, т.к. они уже есть в примерах у Lwip.
Используемая версия Lwip 1.4.0 в SDK нормальная. Её писали не в Espressif (только "портировали" - там всего до 10 вставок и задан свой конфиг) и ошибок в ней практически нет. Те, что есть, это не ошибки, а недочеты с нововведениями и в новых версиях Lwip их и обсуждают. Нам это не требуется. У нас задача освоить пусть и "старый стек" - нет смысла гоняться за номерками.
Пример будет, но позже. Необходимо "культурное" мультиплатформенное внешнее ПО по созданию диска с файлами, дизайн страниц сервера и много другой мелочи, никак не относящейся к ПО на самой ESP8266. Пока это не слеплю - примера не будет. А одному это тяжко и долго...

Например не решен вопрос, что делать со скатыванием закрытых соединений с TIME_WAIT и переполнением от них памяти. Это актуально, когда на HTTP сервер ESP8266 заходят через proxy. Большинство proxy не закрывают соединение первыми (им не нужны "отложения" на 60 сек) и приходится серверу http закрывать их самому, наращивая "отложения" в "TIME-WAIT PCB states" в итак малой памяти ESP8266... А пока соединение не закрыто браузер ждет и выходит "медленный сайт". Остальное с http сервером у меня уже решено (обработка "парсера" страниц, файловая система, запросы и установки всех параметров имеющихся у ESP8266, куки, имитация cgi и другое) и он "летает" - обрабатывает соединения с потоком в свой предел по полосе wifi.
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
Что-то не видать тут никакого “сообщества” – никто не делиться информацией по SDK... :)
Да как бы все пока в зачаточной стадии по ESP8266, сообщество отталкивает отсутствие нормальной оффициальной поддержки.
Я вот потихоньку пишу статьи, вот сегодняшняя http://geektimes.ru/post/242669/
Но это чисто баловство, вчера наконец то с горем пополам собрал компилятор xtensa-lx106-elf-gcc под Win x86, а то в сети под Win x64 он болтается, не очень удобно. C xtensa-lx106-elf-g++ компилятором засада, не собирается, куча ошибок вылазит. Ззаодно libhal от сообщества собрал, вроде пока мои тестовые прошивки нормально работают, сейчас буду пробовать работать напрямую с lwip, без espconn.
Где бы вот нарять исходники libmain, libphy, libpp, libnet80211 для исследования.
 

pvvx

Активный участник сообщества
++ не требуется. "Мало памяти" у ESP8266. Мультизадачка - туда-же. Всё это не актуально на имеющихся ресурсах у ESP8266. Всякие интерпретаторы разных языков с единственной целью - для настройки параметров связи модуля - это "погоня за лейбочками" и не более. Актуально только для обучения создателя такого приложения, но никак не требуется простому пользователю.
Не забываем, что памяти heap у нас всего до 30 килобайт, при этом любое и каждое соединение с сетью требует иметь там резерв от 8 кило, плюс на активные ещё от 300 байт, как минимум ... В итоге имеем всего до десятка килобайт памяти на всё приложение.
Это “частично” компенсируется скоростью проца и увеличения программной части. Но тогда имеем ограничение в размере flаsh с заданной разметкой от Espressif...
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
Мультизадачка - туда-же. Всё это не актуально на имеющихся ресурсах у ESP8266. Всякие интерпретаторы разных языков с единственной целью - для настройки параметров связи модуля - это "погоня за лейбочками" и не более. Актуально только для обучения создателя такого приложения, но никак не требуется простому пользователю.
Абсолютно согласен про многозадачность и то, что всякие интерпретаторы типа lua и micro-python не нужны, чистый Си и только он.

pvvx если не секрет, то откуда так много знаний о ESP8266 ?
 

Andy Korg

Moderator
Команда форума
Да как бы все пока в зачаточной стадии по ESP8266, сообщество отталкивает отсутствие нормальной оффициальной поддержки.
Мало времени еще прошло. Сам только-только начал читать SDK
... вчера наконец то с горем пополам собрал компилятор xtensa-lx106-elf-gcc под Win x86, а то в сети под Win x64 он болтается, не очень удобно....
Вот и я то же специально поставил wi64, что бы компилятор запустить. Под win32 так и не получилось запустить?
 

pvvx

Активный участник сообщества
pvvx если не секрет, то откуда так много знаний о ESP8266 ?
Купил у китайцев десяток модулей и пытаюсь сделать из них то, что мне надо. Всё остальное из инета. Я не проф. программист, на народных поделках бизнеса не делаю (что будет доведено до нормальной стадии всегда выкладываю в открытый доступ). Правда, со времен появления первых MCU (более 25 лет) занимаюсь созданием разных поделок на них, начиная с решения задачи как это сделать, до серийного выпуска (т.е. полный цикл разработки) ...
Вы хотели пример с http без espconn. Взял пару примеров из Lwip http://download.savannah.gnu.org/releases/lwip/

HTTPd_sample https://yadi.sk/d/YPTjTr5UdJbt9

Собран для конфигурации под windows, указанной тут http://geektimes.ru/post/241842/ (но там автор :) не задал правильные опции -D для компиляции Iot в Makefile (!) )

При старте проверяет, находится или нет модуль в режиме STATIONAP_MODE. Если нет, то пытается его поставить данный режим с опциями подключения, указанными в user_config.h.
UART-ы ставятся в 115200 Baud, UART0 и UART1 меняются местами, для последующей загрузки flashиз Eclipse, чтобы не переключать портов.
При старте выводит в UART:

SDK version:0.9.3
NetBIOS init, name 'ESP8266 '
UDP Test port 1025 init
HTTPD init

Тестовый UDPпорт (1025) открывается на соединение ESP8266 к базовой станции.
Запросы в Тестовый UDP порт:

W? – WiFi info (информация по WiFi):

Chip_id: 0099acf1 AP_id:0 sys_time:3957beb2 ADC:21
OPMode:3 SSID:'ESP8266' Pwd:'0123456789' Ch:13 Authmode:4 MaxCon:4 Phu:3 ACon:1
Connect status:5
heapsize: 34096

C? – info Lwip pcb (списки соединений tcp у Lwip):

HeapSize: 33608
Active PCB states:
Port 80|1139 flg:00 tmr:0a03 ESTABLISHED
Listen PCB states:
Port 80|48093 flg:84 tmr:7308752d LISTEN
TIME-WAIT PCB states:
Port 80|1138 flg:30 tmr:09da TIME_WAIT

H? - system_get_free_heap_size:
HeapSize: 34096

R? - system_restart()

0? - system_set_os_print(0) (отключить вывод системной информации в UART)

1? - system_set_os_print(1) (включить вывод системной информации в UART)

PS: беда с пробелами, после английских символов - так работает местный движок, при вставке текста из других редакторов и исправлять надоело :(
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
Вот и я то же специально поставил wi64, что бы компилятор запустить. Под win32 так и не получилось запустить?
Все получилось, читайте мою статью http://geektimes.ru/post/242669/, там в начале сылки на Espressif ESP8266 DevKit x86 под Win x86

Собран для конфигурации под windows, указанной тут http://geektimes.ru/post/241842/ (но там автор :) не задал правильные опции -D для компиляции Iot в Makefile (!) )
Собсно автор этой статьи Я ;) А что там не верно в Makefile? Скиньте правильный, я подправлю в DevKit.

За пример спасибо, сейчас изучу.
 

pvvx

Активный участник сообщества
Собсно автор этой статьи Я ;)
А там и сказано " :) "
CFLAGS = -Os -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DLWIP_OPEN_SRC -DPBUF_RSV_FOR_WLAN -DEBUF_LWIP
За пример спасибо, сейчас изучу.
Там обычный демо Httpd и Netbios от Lwip.
Netbios для приколу - позволяет обращаться по имени в локальной сети http://имя wifi модуля. Длина имени ограничена 16 символами - берутся первые 16 от имени wifi ...
Это может вызвать радостный ажиотаж броузера с поиском WPAD файла :)
http://ubuntu-faq.blogspot.ru/2013/11/wpad-proxy-pac.html
Wireshark:
49.604574000 сек 192.168.4.101 -> 192.168.4.1 HTTP GET /wpad.dat HTTP/1.1
116.779580000 сек 192.168.4.101 -> 192.168.4.1 HTTP GET /wpad.dat HTTP/1.1
...
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
Сверху Снизу