Разработка ‘библиотеки’ малого webсервера на esp8266.

pvvx

Активный участник сообщества
Хеш Пирсона 8 бит
....
// T table for Pearson hashing from RFC3074, хотя не думаю, что это принципиально:)
unsigned char T[256] = {
.....
};
Как по мне, по быстродействию вполне сравнимо с MPFS2
Вот эта T[256] отожрет и так малую память RAM.
На 256 байт будет меньше heap или bss.
Как раз в связи с этим счас пытаюсь оптимизировать систему обработки имен переменных.
Имена, строки к примеру с os_printf("отъем память!"), помещаются в память... Короче разбираюсь и изучаю как транслируется и распределяется у данного проца просматривая итоговые листинги asm и т.д.
Сборка SHERTS не дает листингов asm и т.д. Надо дописывать маке-файлы.
Я не уверен. Причем эта неуверенность появилась после того, как combine при разной последовательности включения файлов дало неполный размер выходного bin - что-то вроде 506 с копейками вместо 520 с копейками
Там ещё доп. инфа привязывается к бинарнику. Точно не смотрел, но разметка то для загрузчика bios и распределения что куда раскидывать по сегментам должна быть.
 
Последнее редактирование:

pvvx

Активный участник сообщества
И последний вопрос - а когда ждать альфа релиза исходников прошивки ? :)
Когда "рак на горе свиснет" :).
Сам Web, в части TCP/IP давно работает. Счас можно выложить версию с обеспечением приема по HTTP файлов. Но никому не нужен голый web, без программ компоновки диска, обработки переменных и готовых базовых HTM страниц с нормальным дизайном, обеспечивающих минимальный функционал - настройку WiFi + возможность подключения других библиотек. Я как-бы взялся за сам web, а внешнее ПО по сборке диска и дизайн страниц делать пока не собираюсь. Это всё переплетено между собой. Как кто подключится и даст нормальный вид программе создания диска и веб страничек, стразу будет и первый базовый более-менее релиз. Без этих доп.частей я пишу (балуюсь) исключительно только ради своих целей (а этот процесс может быть вечным). Ведь пока не требуется стыковки с другими и не определен минимальный функционал...
Например - надо или нет в базе иметь загрузку прошивки:
Если диск не прошит, то можно добавить базовую команду прошивки из эксплорера, как это сделано у Микрочипа в MPFS2.
Ну и т.д. А этих т.д. очень много :)
Плюс ещё большая часть, связанная с подключением TCP/IP сокетов с использованием внутренней базы tcp_srv_conn работающей с Lwip. Сам web сидит на ней. Т.е. у нас система, имеющая ядро с tcp_srv_conn. Для одного web их проще слить воедино для оптимизации. Но тогда пропадает возможность по открытию других TCP/IP сокетов, к примеру для реализации туннеля UART-TCP и т.д.
У туннеля UART-TCP уже аппаратные зависимости - требуется нога RTS/CTS и разные её функциональные реализации :)
В заголовке (первом сообщении темы) описан базовый функционал, но варианты его реализации зависят от запросов и пожеланий пользователей. А их пока нет -> (следовательно) нет и реализации. :)
HTTP страницы сервера на сегодня созданы исключительно ради отладки, а не для использования в каких-то приложениях на ESP8266 - это и указано - тема находится в разделе не приложений, а работы с SDK и требование готовых приложений тут игнорируются.

PS: Собрал очередной вариант свалки исходников, что вышло после мелкой чистки. Ссылки см. в первом сообщении темы.
 
Последнее редактирование:

A_D

Active member
pvvx, понял теперь в чем дело, к сожалению я не особо хороший программист. из прикладного - только с# более менее знаю и С (чуть С++) для МК (в основном на атмегу писал, немног наши кортексы знаю миландровские).
Помочь могу с железом, если надо - в Альтиуме делаю схемы\платы.
А сейчас диск этот собирается по скрипту с бубнами, так ?
Кст, еще вопрос (извиняюсь если нубские вопросы задаю... ибо не силен в этом) - посмотрел странички код и там были поля к примеру UART скорости, в коде получается пишем\читаем новое значение оттуда по полю
name='uart.1.baud' верно ? (насколько я понял обработка этого дела в файле web_int_vars.c)

А по поводу реализации - я как не шибко хороший программист, скорее пользователь, вижу идею эту так (могу ошибаться в чем то, ибо это только мое ИМХО) исходя из дополнения основных целей проекта:
>> 1) Управление конфигурацией WiFi модуля и приложений на ESP8266 с помощью любого устройства с интернет браузером не ниже версии HTTP/1.0.
и сюда по идее сразу подключается вопрос о задании логина\пароля на все сразу(при входе) или только на настройки модуля. кст, дебаг функции у Вас под паролем вроде как, ну я ввел логин admin и пароль пустой - браузер показывал, мол грузится и ничего не обновлялось, я подождал секунд 15, потом зашел опять на главную страничку модуля и опять перешел по ссылке на дебаг страничку - все перешлось и не спрашивало пароля, так и должно было быть ?

>> 2) Возможность подключения программных модулей для работы с разной периферией.
и было бы шикарно, если бы в коде или рядом сразу имелись бы примеры использования spi,pwm,adc и т.д.
для эдакого быстрого старта получается шаблон, с примерами или оч кратким гидом, что и как где дописать или где лежит. (в этом хотя б тоже могу помочь, посмотрев как юзеру - где чего непонятно и описать что за чем в мини гиде пошагово)
 

Vit

Member
Насчет таблицы понятно. Я привык, что в МК флеши полно(по сравнению с ОЗУ) и const по возможности лежит во FLASH на борту. Гугл подогнал:) статью с оценкой нескольких хэш функций (без таблиц), выбиравшихся для очень похожих требований.
Чуток размышлизмов и маленьких воросов.
По описанию требований к ФС не нашел предполагаемой дисциплины конкурентной работы при записи. Запись (а она отжирает время - хоть какая-то 1 мс на страничку, но время, а это ОЗУ) должна быть монопольно отдана привилегированному пользователю, или "кто первый встал, того и тапки"?
Начал считать метаданные и решил переспросить - сколько сейчас доступно пользовательской FLASH в GD25Q40B для диска?
Вообще запись данных не при первоначальной заливке возможна? Требуется ли связывать в метаданных фрагментировнные участки?
Имеет ли смысл для этого думать о битовой таблице занятых страниц? Всего-то uint16_t для одной копии если ограничиться GD25Q128С. И если предположить, что фрагментация будет, то одна копия для файла с картой его занятых страниц, номер страницы начальной и уже можно думать как занять свой размер при записи...
 

pvvx

Активный участник сообщества
Начал считать метаданные и решил переспросить - сколько сейчас доступно пользовательской FLASH в GD25Q40B для диска?
Описано выше: Места там мало (область от 0x1E000 до 0x3e000).

Пока выделено было так. Начало зависит от размера файла 00000_eagle.app.v6.bin.
Можно скомпоновать файлы и по другому в flash. Но:

The "bin" files are as follows:
1) blank.bin, provided by Espressif, burn to 0x7E000 address;
2) eagle.app.v6.flash.bin, as compiled, burn to 0x0000 address;
3) master_device_key.bin, from the Espressif server application, burn to 0x3E000 address;
4) eagle.app.v6.irom0text.bin, as compiled, burn to 0x40000 address;
5) esp_init_data_default.bin, provided by Espressif, burn to 0x7c000 address

Отмеченные жирным переместить не просто. Надо глубоко ковырять...

Вообще запись данных не при первоначальной заливке возможна? Требуется ли связывать в метаданных фрагментировнные участки?
Имеет ли смысл для этого думать о битовой таблице занятых страниц? Всего-то uint16_t для одной копии если ограничиться GD25Q128С. И если предположить, что фрагментация будет, то одна копия для файла с картой его занятых страниц, номер страницы начальной и уже можно думать как занять свой размер при записи...
FAT не хочу - исходники даны и будут даны - организуйте диск как хотите.
Время записи flash указано в спецификации и зависит от метода. У данной flash есть 256-Byte Page Buffer.
А сейчас диск этот собирается по скрипту с бубнами, так ?
Никаких бубнов. MPFS2 выдает много лишнего и в диск кидает лишнее. Требуемый формат диска был описан выше. MPFS2 я по началу так искривил, чтобы она выдавала все примененные на диске переменные... Но дальше её кривить пока не хочу - условие тоже описал, почему. Исправить её для нормального диска = пол часа, но это продукт Микрочипа, а надо свой - там дольше вырезать лейбы микрочипа :).
 
Последнее редактирование:

pvvx

Активный участник сообщества
В следующей версии будет уже поддержка contenta multipart/form-data.
Там помесь передается - или файл, или опять переменные...

Пример c MS-Explorer что говорит web при приеме фалов: Load blk len: 399

-----------------------------7df22f37711be\r\n
Content-Disposition: form-data; name="test"; filename="readme.txt"\r\n
Content-Type: text/plain\r\n\r\n
1234567890\r\n
-----------------------------7df22f37711be\r\n
Content-Disposition: form-data; name="start"\r\n\r\n
0x1B000\r\n
-----------------------------7df22f37711be\r\n
Content-Disposition: form-data; name="stop"\r\n\r\n
0x1B000\r\n
-----------------------------7df22f37711be--\r\n


Пример с Google Chrome: Load blk len: 391

------WebKitFormBoundaryugGNBVFOk6qxfe22\r\n
Content-Disposition: form-data; name="test"; filename="readme.txt"\r\n
Content-Type: text/plain\r\n\r\n
1234567890\r\n
------WebKitFormBoundaryugGNBVFOk6qxfe22\r\n
Content-Disposition: form-data; name="start"\r\n\r\n
0x1B000\r\n
------WebKitFormBoundaryugGNBVFOk6qxfe22\r\n
Content-Disposition: form-data; name="stop"\r\n\r\n
0x1B000\r\n
------WebKitFormBoundaryugGNBVFOk6qxfe22--\r\n


Всё это будет разгребаться. Boundary запоминается из заголовка HTTP и ...
Сейчас это уже в отладке и размышлениях как проще слепить...
 

Alex

Member
To pvvx.
Получил сегодня с почты 25Q128. Стоит припаивать? Ваша крайняя сборка будет ее поддерживать?
Файлы для теста я так понял в образ монтируются? Через Web еще нельзя их грузить?
И еще вопрос знатокам Web. Как настроить сервер что бы при обращении по любому адресу переадресация шла на ip серевера?
 

pvvx

Активный участник сообщества
To pvvx.
Получил сегодня с почты 25Q128. Стоит припаивать? Ваша крайняя сборка будет ее поддерживать?
Работает она. Но в текущей выложенной помойке что-то не то кинул - совсем старый вариант с flash. Скоро на подправленную заменю...
Файлы для теста я так понял в образ монтируются? Через Web еще нельзя их грузить?
Нормальной программы создания диска сервера ещё нет. Пока диск загружается в среде Eclipse или FLASH_DOWNLOAD_TOOLS_v0.9.x для больших flash с адреса 0x80000 (после 512к).
И еще вопрос знатокам Web. Как настроить сервер что бы при обращении по любому адресу переадресация шла на ip серевера?
Такого не бывает, или не я не понял про что вопрос.
 

pvvx

Активный участник сообщества
Кто подскажет оптимальное решение таких насущных вопросов:

Имеем туннель TCP2UART на ESP8266. Стандартно, поток в одну сторону по TCP через WiFi на данном модуле у нас за 600 килобайт в сек.

UART tx имеет fifo в 128 байт. При скорости COM порта (UART tx в данном случае), к примеру, в 3 Mbits/sec, имеем такую картину:
TCP-UART3MB.gifTCP-UART3MB_wire.gif
Это вариант включения передачи из буфера TCP пакета кусками, по размеру FIFO TX UART, путем зарядки таймера. Задаю таймеру шаг в 1 ms– меньше, никак. Как ровно слить поток с TCP/IP в UART? (При 10 Mbits/s он уже сам ровный – по размеру принятых пакетов – пока проц перекидывает байты в UART, они уже успевают вылезти :) , при менее 500 кбит – тоже ровный – тормозим стек TCPпо полной – весь канал заполняется сообщениями о TCP ZeroWindow - только это и передается :) )

Для линейности потока надо передать в секунду около 600000/128 = 4687.5 пакетиков размеров в FIFO UART. Делал и по прерыванию опустошения FIFO c триггерами и т.д.– тоже дырки выходят. При 10 Мбитах FIFO UART уже хватает для передачи непрерывным блоком пакетов TCP. Пакет у нас к 1460 байт данных, но всё равно приходиться тормозить передающего данные клиента по каналу TCP за счет сужения окна приема… Очень не охота делать ещё громадные статические буфера для UART, в и так малой памяти…

Прием, RX UART, тоже не в радость. Пока использую буфер в 256 байт, от BIOS и тоже по прерыванию (иначе это бесполезно оставленная память, распределенная BIOS). Пока через таймер – аналогично – принят первый байт, заряжается таймер и через 1..5 ms предается всё что набралось до этих 256 байт. Выходит передача пакетами в пределе до 256 байт и от этого падает скорость соединения...
 
Последнее редактирование:

Alex

Member
Работает она. Но в текущей выложенной помойке что-то не то кинул - совсем старый вариант с flash. Скоро на подправленную заменю...
Нормальной программы создания диска сервера ещё нет. Пока диск загружается в среде Eclipse или FLASH_DOWNLOAD_TOOLS_v0.9.x для больших flash с адреса 0x80000 (после 512к).
Такого не бывает, или не я не понял про что вопрос.
Я немного не так выразился. Я имел ввиду файлы для скачивания. Вы с даташитом на 25q128 экспериментировали. Они тоже в образ закатываются?

Бывает у провайдера интернета, когда деньги на счете заканчиваются ;)
Суть что не зная адреса на страницу WiFi точки не попасть. Нужно что при наборе любого адреса на нужный попадали. Видимо DNS нужен.
 

pvvx

Активный участник сообщества
Извиняюсь что вмешиваюсь, но можно задавать таймер в микросекундах, вот выдержка из osapi.h:
#ifdef USE_US_TIMER
#define os_timer_arm_us(a, b, c) ets_timer_arm_new(a, b, c, 0)
#endif
Задаю 1 ms. Меньше - только аппаратно. На графике выхода и показано, что идет задержка менее 1 ms.
Вывод FIFO на 3Mb/s = 128 символов * 10 бит (1 старт + 8 бит + 1 стоп) / 3 000 000 baud = 0.000427 сек (427 мкс)
Применение system_os_post и типа считаю неоправданным - слишком большой расход памяти на структуру и ещё статической... И такой вечный опрос, пуст ли буфер у UART, займет всё время CPU не оставив на другое.
С микросекундами таймер не пробовал - не вериться, что будет работать...
 
Последнее редактирование:

pvvx

Активный участник сообщества
Я немного не так выразился. Я имел ввиду файлы для скачивания. Вы с даташитом на 25q128 экспериментировали. Они тоже в образ закатываются?
Что за "образ"? Файлы диска, на больших flash, закатываются за начальной областью занятой ПО и SDK - за первыми 512кб. За 1Mb и "кеширование" flash у установок SDK "кешам" прекращается...
Как экспериментировать с даташитом?
Бывает у провайдера интернета, когда деньги на счете заканчиваются ;)
Суть что не зная адреса на страницу WiFi точки не попасть. Нужно что при наборе любого адреса на нужный попадали. Видимо DNS нужен.
Про это писал где- то на форуме ранее.... Рабочий пример "DNS" дан и вложен в исходники. (Только не DNS - DHCP уже есть в системе, а netbios - для доступа по имени.) WPAD и PAC файл вкладывается в сервер... "Бывает у провайдера интернета" - При наличии подключения к инету с другой дырки будет бардак.
Т.е. это не относится к библиотеке HTTP сервера - реализуется пользователем, путем управления сборкой и вложения необходимых файлов в диск сервера.
 
Последнее редактирование:

webself

New member
А насколько сложно добавить в код вашего веб-сервера, чтобы начальный доступ был не по IP, а по имени хоста?
Например по "esp".

Было бы здорово удобнее обычным домохозяйкам настраивать такие устройства.
Адрес "192.168.1.4" у таких людей легкий испуг вызывает.

pvvx, я вам еще в личку написал, поглядите плиз.
 

pvvx

Активный участник сообщества
А насколько сложно добавить в код вашего веб-сервера, чтобы начальный доступ был не по IP, а по имени хоста?
Например по "esp".

Было бы здорово удобнее обычным домохозяйкам настраивать такие устройства.
Адрес "192.168.1.4" у таких людей легкий испуг вызывает.

pvvx, я вам еще в личку написал, поглядите плиз.
Это реализовано давно.
При компиляции раскомментировать в user_config.h: //#define USE_NETBIOS 1
Будет имя по названию (SSID) WIFI AP. К HTTP серверу это не относится. Менять имя на ходу, при смене у WIFI не вижу смысла. После перезагрузки ESP8266 оно сменится.
А здеся тема не для домохозяек и не о готовых для пользователя приложениях. Тут библиотека HTTP сервера для текущего SDK и требует знаний у пользователя СИ и прочего... Когда выйдет готовый продукт для домохозяек - будет соответствующая тема в соответствующем разделе форума или ... :)
 

pvvx

Активный участник сообщества
Извиняюсь что вмешиваюсь, но можно задавать таймер в микросекундах, вот выдержка из osapi.h:
#ifdef USE_US_TIMER
#define os_timer_arm_us(a, b, c) ets_timer_arm_new(a, b, c, 0)
#endif
Работает (всё заменил на ets_timer_arm_new() ):
TCP-UART3MB.gif
TCP-UART 3Mbis/s
Когда причешу код и подрихтую RX в UART - выложу.
 
Последнее редактирование:

Vit

Member
Смотрю в datasheet GD25Q40 и не наблюдаю команд PAGE_ERASE и PAGE_WRITE (как в, например, M25PE40). Есть только PAGE_PROGRAM. А, например, в DS M25P40 - явно указано, что команда с таким именем изменяет содержимое битов только с 1 на 0, в M25PE40 - то же. В DS GD25Q40, W25Q40 и N25Q16 явного указания не находится, но опкоды вроде как совпадают. Если в GD25Q40/W25Q128 командой PAGE_PROGRAM не перетираются страницы, то что-то становится мне совсем грустно насчет быстрой записи без затыков на стирание сектора - по DS GD25Q40 Sector Erase time 100 ms typical.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Смотрю в datasheet GD25Q40 и не наблюдаю команд PAGE_ERASE и PAGE_WRITE (как в, например, M25PE40). Есть только PAGE_PROGRAM. А, например, в DS M25P40 - явно указано, что команда с таким именем изменяет содержимое битов только с 1 на 0, в M25PE40 - то же. В DS GD25Q40, W25Q40 и N25Q16 явного указания не находится, но опкоды вроде как совпадают. Если в GD25Q40/W25Q128 командой PAGE_PROGRAM не перетираются страницы, то что-то становится мне совсем грустно насчет быстрой записи без затыков на стирание сектора - по DS GD25Q40 Sector Erase time 100 ms typical.
flashs.gif
W25Q40BV.pdf и W25Q128FV.pdf вроде совпадают... главное, что пишется стандартным ПО. Но вроде есть хитрость - FLASH_DOWNLOAD_TOOLS пишет большие flash, если начинать запись с низких адресов и лить непрерывным блоком... :)
Что-то надо поковырять в её исходниках.
Доделаю UART-TCP и сделаю пробную заливку flash c эксплорера. Там скорости и узнаем.
 
Последнее редактирование:

Vit

Member
Посмотрел функцию system_upgrade_internal - похоже таки стирается только секторами - данные копируются в аллоцируемый буфер, в зависимости от условий вызывается spi_flash_erase_sector и уж потом вызывается spi_flash_write :(
В at_exeCmdUpdate то же, только "прямоугольнее" -
spi_flash_read(60 * 4096, (uint32 *)&upFlag, sizeof(updateFlagType));
upFlag.flag = 1;
spi_flash_erase_sector(60);
spi_flash_write(60 * 4096, (uint32 *)&upFlag, sizeof(updateFlagType));
// spi_flash_read(60 * 4096, (uint32 *)&upFlag, sizeof(updateFlagType));
os_delay_us(10000);
system_reboot_from(0x00);
 
Последнее редактирование:

pvvx

Активный участник сообщества
Посмотрел функцию system_upgrade_internal - похоже таки стирается только секторами - данные копируются в аллоцируемый буфер, в зависимости от условий вызывается spi_flash_erase_sector и уж потом вызывается spi_flash_write :(
При потоке по TCP, примем 500кбайт/c, стирание страницы у 128M типичное по доку 150ms, выходит, что предел будет к 64k/0.15 = 426.666667 кбайт/сек
Если стирать по сектору, то 4к/0.1 = 40 кбайт/сек
Это без учета времени записи. Ещё не глядел, возможна или нет запись и стирание одновременно разных секторов... Но судя по Chip Erase Time typ 40, max 200 sec - нет.
Для скорости придется стирать страницами по 64k.
Для этого у нас имеются процедуры, указанные в eagle.rom.addr.v6.ld:
SPIEraseArea
SPIEraseChip
SPIEraseBlock
SPIEraseSector
Учитывая, что буфер стека TCP на прием для каждого соединения у нас в пределе размера максимального окна (~5706 байт), то по мере поступающих сегментов (в пределе 1540 байт) мы можем и оперировать. Для скоростной записи возможно использовать предварительный запрос по HTTP на стирание области. Потом уже заливка. Как реализовывать – буду думать, но великая скорость заливки диска пользователю не требуется, т.к. это делается однократно за жизнь устройства. :)
 
Последнее редактирование:
Сверху Снизу