SDIO Client

Grem_line

New member
Хочу приспособить ESP8266 для передачи по WiFi потокового видео. Требуется связать модуль с вычислителем для того, чтобы передавать/принимать пакеты данных. При этом задача одного ESP8266 - просто принимать пакеты от вычислителя и выдавать в виде UDP-пакетов другому ESP8266. Второй должен принимать WiFi UDP-пакеты и выдавать своему вычислителю. Скорость обмена модуля с вычислителем должна быть как можно большей (где-то 40-50 Мбит/с). Думаю задействовать SDIO, только не знаю как. Сейчас экспериментирую с SPI. Но скорости маловато. В режиме сервера на выдачу из ESP удалось получить среднюю скорость около 40 (частоту SPI ставлю 80МГц), в режиме сервера на прием не выходит больше 12 Мбит/с при частоте 40МГц (на 80 не работает), а в режиме SPI-slave вообще беда - начинает сбиваться на частоте SPI больше 5МГц.
В качестве вычислителей использую CubieBoard2 под RTOS собственной разработки. Одна цифрует камеру, жмет в h.264 и выдает, а вторая принимает, декодирует и выводит на монитор HDMI. Модули ESP8266 (NodeMCU) программирую через ARDUINO-IDE.
На FullHd (1920x1080@30) и связью c WiFi модулями по SPI имею периодические тормоза.

Пробовал работать с ESP32 - почему-то показалось хуже. И соединение устанавливает дольше и через раз, и по скорости медленнее.

Кто-нибудь знает, как использовать SDIO-Client в ESP8266 для передачи данных?
Подскажите, где найти примеры или что-то в этом духе...
 

pvvx

Активный участник сообщества
Сейчас экспериментирую с SPI. Но скорости маловато. В режиме сервера на выдачу из ESP удалось получить среднюю скорость около 40 (частоту SPI ставлю 80МГц), в режиме сервера на прием не выходит больше 12 Мбит/с при частоте 40МГц (на 80 не работает), а в режиме SPI-slave вообще беда - начинает сбиваться на частоте SPI больше 5МГц.
Предельная долговременная скорость передачи в TCP с Flash в режиме Web сервера у ESP8266 с CPU на 160 МГц, составляет 1.1 мегабайт в сек (80 МГц -> 800..900 килобайт/c). TCP имеет дуплексную передачу - на каждые 2 пакета приходит ACK. При полной 1 к 1 дуплексной загрузке и 80 МГц реальный поток может упасть ниже 600 килобайт в сек в одну сторону. Ограничение имеет большую зависимость от кол-ва принятых/переданных пакетов и размера пакетов. ESP8266 не успевает программно обрабатывать большое кол-во UDP пакетов, очень много пакетов WiFi вообще скипается в приемной и передающей части дров его WiFi.
У ESP8266 phy HT20, а у ESP-32 - HT40. Это дает ESP-32 предельный долговременный поток TCP при передаче в одну строну к 1.6 мегабайт в сек, с пиками в 1.8 МБ/сек.
Передача данных с flash ни как не влияет на данные скорости, а flash включена на SPI.
UART - влияет, из-за медленной возни CPU с регистрами UART через тормозной fifo шины и дурацких лишних команд CPU сброса кэш, которого у него нет, да синхронизации шин, которые кроме лишних тактов CPU ничего не делают. Шина то на периферию контроллеров у ESP8266 всего 26 МГц.
При устранении лишних команд правильными опциями компилятору UART работает и на 10 Мбит, но это занимает большую часть времени занятости CPU ESP8266 и предельный трансфер дров WiFi и LwIP страдает на 50%. SPI немного лучше (в 2 раза минимум), за счет меньшего кол-ва обращений через медленную шину к регистрам контроллера SPI для получения того-же соотношения кол-ва байт в потоке.
На HT20 никаких видео потоков в природе не встречается. Ну если только "видео" не 64x64 точки и пару бит яркости с сенсора мышки :)
ESP-32 вообще программный тормоз, если код и данные не лезут в кэш XIP. Уровень производительности падает примерно до 10 МГц ARM.
Та и у данного семейства ESP нет нормального описания и вообще DMA. Без многолетней специфически заточенной оптимизации под них простых задач их обгоняют любые другие MCU с частотами в десяток МГц. Беда в компоновке SoC со множественным просчетами и ошибками Espressif, а не в типе ядра CPU.
Помучаетесь годик, доведете поток UDP в одну сторону у ESP-32 до 2-х МБайт в сек с 5% потерей и перегревом чипа. Это показывают его тесты (iperf).
 
Последнее редактирование:

Алексей.

Active member
Grem_line,
Решал похожую задачу на esp32, уперся в неожиданные лаги, вроде и скорость нормальная, но лагает периодически без причины, на 264-ом кодеке можно принять часть запоздавших слайсов от предыдущего кадра, который уже восстановили с кривыми артефактами, и не все слайсы для текущего кадра и тоже восстановление дает неожиданные артефакты, в общем не продать решение.
а в режиме SPI-slave вообще беда - начинает сбиваться на частоте SPI больше 5МГц.
Пробовал работать с ESP32 - почему-то показалось хуже
На макете esp32 spi подключен слейвом проводами 15-20 см. работает на 12мегабит, беда закончилась когда таск работающий с spi запустил на первом ядре, на нулевом остались таски работающие с ip
 
Последнее редактирование:

Grem_line

New member
Предельная долговременная скорость передачи в TCP с Flash в режиме Web сервера у ESP8266 с CPU на 160 МГц, составляет 1.1 мегабайт в сек (80 МГц -> 800..900 килобайт/c).
Извините, не понял Вас. При чем тут TCP - я использую UDP пакеты для передачи видео по протоколу RTSP. Кроме того, мне вовсе не нужно забирать данные из Flash - данные поступают из внешнего контроллера по каналу SPI прямо в оперативную память ESP. Сейчас это сделано немного кривовато: ESP работает в режиме мастера, поэтому пришлось добавить лишний провод, по перепаду уровня на котором ESP узнает о наличии нового пакета, принимает его по SPI и выдает по WiFi в виде UDP-пакета. Сейчас все работает, но при больших объемах некоторые UDP-пакеты теряются. Получается, что система работает несколько секунд, потом происходит потеря и картинка замирает до прихода очередного ключевого кадра.
Мне думается, что проблема вызвана тем, что ключевые кадры не помещаются в один UDP-пакет, а при дроблении на сегменты приходят слишком часто - нужно попробовать вставить задержки между сегментами. Скорость передачи реально составляет около 8-9 МБит. После праздников буду пробовать.
 

Grem_line

New member
При выдаче UDP-пакетов вставил адаптивную задержку - чем длиннее пакет, тем больше. Все заработало более-менее прилично. Тем не менее, хотелось бы более быструю связь между ESP и вычислителем.
Так как же насчет SDIO-неужели никто не пробовал?
 

Алексей.

Active member
При чем тут TCP - я использую UDP пакеты для передачи видео по протоколу RTSP.
Это ваш выбор, rtsp кроме udp транспорта, есть ещё и tcp транспорт, с заголовком определяющим номер канала и длину данных.
Когда на esp32 в rtp потоке я терял udp пакеты, пробовал использовать tcp, потерь не стало, но лаги остались, забросил я его, медиатек как оказалось получше.
 

Grem_line

New member
Когда на esp32 в rtp потоке я терял udp пакеты, пробовал использовать tcp, потерь не стало, но лаги остались
Используйте механизм асинхронного обмена с подтверждением.
Как выяснилось, дело было не в бобине:)
Оказалось, что передача данных по WiFi на двух esp8266 идет абсолютно чисто, без каких-либо потерь пакетов. Я убедился в этом, добавив контроль целостности информации в принимающем esp.
Проблема обнаружилась в задаче приема пакетов SPI от esp в CubieBoard! Просто оказалось, что я запустил ее с более низким приоритетом, чем задачи декодирования и отображения :oops:
Простая установка наивысшего приоритета для этой задачи сходу решила все проблемы.
Вот уже третий час гоняю full-hd видео и пока ни одного сбоя.

Кстати, несмотря на то, что UDP-пакеты не требуют подтверждения, сама низкоуровневая передача любых адресных пакетов по WiFi осуществляется с подтверждением (и переотправкой пакета при отсутствии подтверждения). Поэтому не вижу смысла делать еще что-то вручную.
пробовал использовать tcp, потерь не стало, но лаги остались, забросил я его
Не наблюдаю (пока) никаких лагов, потерь, повторов и т.д. Правда, это esp8266. На esp32 у меня появились проблемы сразу: подключение к точке доступа на нем почему-то занимало секунд 20 и происходило через раз (на каждый второй раз выводилась какая-то ошибка, приходилось жать на ресет). На старом добром esp8266 подключение происходит с первой попытки, менее чем за секунду. Уж не знаю почему.
 

Grem_line

New member
скорость потока какая? И,правильно ли я понял, что это на Ардуино ИДЕ реализовано?
Скорость где-то около 7-8 Мбит/сек. ESP программировал под Ардуино ИДЕ.
CubieBoard - под RTOS собственной разработки.
Сегодня хочу попробовать поднять скорость - есть момент при выдаче пакетов esp8266 по USB:
Код:
  Del = 1;
  repeat:
   Udp.beginPacket(ip_addr,port);
   Udp.write(Buf,Length);
   if (0==Udp.endPacket())
   {
    delay(Del);
    Del++;
    if (Del > 32)
    {
      Serial.printf("Send fail!\n");
    } else goto repeat;
   }
Если функция Udp.endPacket() возвращает 0 - значит пакет не выдан и нужно повторить выдачу. Сейчас перед повтором делается задержка, возрастающая с каждой неудачей. Нужно попробовать как-то это дело улучшить...
 

Сергей_Ф

Moderator
Команда форума
@Grem_line
не знаю как вам, но goto....
вот так поизящнее, имхо
Код:
Del = 0;
do {
   delay(Del++);
   Udp.beginPacket(ip_addr,port);
   Udp.write(Buf,Length);
} while(  0==Udp.endPacket() && Del<=32 );
if (Del >32 ) Serial.printf("Send fail!\n");
 

Grem_line

New member
не знаю как вам, но goto....
Это старая фишка, еще в 90-е одна солидная фирма проверяла качество ПО. В результате составили заключение, в котором писалось: "программа написана очень хорошо, так как в тексте нет ни одного goto".:)
Если посмотреть результат компиляции моего и вашего вариантов (ассемблер), уверяю, разницы не будет.
Хотя не спорю, ваш смотрится приятнее...
Есть правда один момент - вызов функции delay(0) тоже отъедает какое-то время. В этой функции вызываются обработчики WiFi и TCP/IP. Для esp8266 delay не просто тормозит скетч, а поддерживает систему, занимая при этом время даже при параметре, равном нулю.
Для повышения быстродействия лучше использовать не do-while, а while, чтобы не делать лишнюю задержку при первом проходе.

Померил битрейт сырого потока - на роликах, что гоняю, получается в пиках где-то до 6.5 Мбит/с. Это если измерять за секунду. Если усреднять за 10 секунд, получается порядка 2 Мбит/с.
 

Сергей_Ф

Moderator
Команда форума
а while, чтобы не делать лишнюю задержку при первом проходе.
тут на вкус и цвет, но просто while не получится - Udp.endPacket() не будет ещё определен при первом заходе. Можно немного переделать без delay перед и выходить из цикла по break, тогда.
Код:
Del = 1;
do {
   Udp.beginPacket(ip_addr,port);
   Udp.write(Buf,Length);
   if   ( 0==Udp.endPacket()) break;
   else delay(Del++);
} while(  Del<=32 );
if (Del >32 ) Serial.printf("Send fail!\n");
Померил битрейт сырого потока - на роликах, что гоняю, получается в пиках где-то до 6.5 Мбит/с. Это если измерять за секунду. Если усреднять за 10 секунд, получается порядка 2 Мбит/с.
Вот точно такие значения я получил в роутере на esp8266. Правда для TCP, но и на SDK. Мне сказали, что я вру :). Что то мне подсказывает, что дальнейшие ваши действия к улучшениям не приведут. Вы достигли теоретического потолка для esp3266 :)
 

Grem_line

New member
Что то мне подсказывает, что дальнейшие ваши действия к улучшениям не приведут. Вы достигли теоретического потолка для esp3266 :)
Похоже на то. Но это нормально, мне по ТЗ надо подключить камеру с разрешением 720p, похоже что получится. На худой конец, увеличу степень сжатия, или прорежу вдвое частоту кадров.
Просто я не вижу альтернативы ESP - другие модули WiFi работают по непонятным закрытым протоколам, если брать дрова из линукса, то вылазит такой клубок, который мне во век не размотать. С меня хватило написания собственного стека TCP/IP или собственного драйвера USB UHCI|OHCI|EHCI...
 

Grem_line

New member
@Сергей_Ф, тут появилась одна проблема: При больших пиковых нагрузках начинаются сбои - фактическая длина пакета отличается от той, которая записывается в заголовке. UDP пакеты то приходят короче, чем должны на несколько байт, то длиннее (всегда почему-то на 180 байт).
Это приводит к появлению артефактов на изображении. Если после выдачи каждого пакета вставлять задержку, то все нормально. Только как-то это криво. Если функция endPacket() возвращает 0, то пакет не выдан. Как я понимаю, очередь на выдачу переполнена. Сейчас я просто делаю задержку и повторяю выдачу. Наверное, есть ситуации, когда пакет выдается частично... Не знаете ли Вы какой-нибудь функции, чтобы до выдачи опеределить - есть ли свободное место для пакета?
 

Grem_line

New member
Как выяснилось, пакеты зарезаются не в WiFi, а при обменах по SPI. Я ставил скорость 80МГц, перевел на 40 и сбои практически ушли. Вона как!
 

Grem_line

New member
SDIO что в заголовке делает?
SDIO - это протокол обмена контроллера с периферией, более быстрый, чем SPI за счет того, что используются параллельно четыре линии данных. С помощью SDIO подключается не только флеш, но и большинство WiFi-модулей. Просто разобраться с тем, как работает готовый модуль WiFi по SDIO я чего-то не смог (надо поднимать весь WiFi), а ESP уже сам умеет работать с WiFi и его можно запрограммировать как угодно.
 
Сверху Снизу