Jump to content
    

Помогите с примером LWIP + LAN8720A + STM32Н743ZIT6 без RTOS

Приветствую!
Прошу помочь с гарантированно рабочим примером, который хоть что-то делает.
Пробовал разные примеры из сети, с сайта STM,а также сгенерированные кубом.
Мне надо сделать UDP-клиент, но сдвигов нет.
Всё остальное на процессоре уже работает, только с ETH заминка вышла.
Активности нет, на пинги не реагирует. Только светодиоды мигают, но это я так понимаю функция PHY.
Или подскажите последовательность шагов, что и в каком порядке запускать, чтобы оживить функционал.

 

Share this post


Link to post
Share on other sites

Приветствую!
Получилось вернуться к этому проекту.
Мне нужно через Ethernet посылать данные по UDP. Вроде удалось завести это дело.
Насколько я понял, минимальная последовательность для отправки одного UDP пакета такая:

p_udp = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_POOL);
err = pbuf_take(p_udp, &buff, size);
err = udp_sendto(pcb, p_udp, &client, udp_d_port);

Исходя из этого два вопроса:
1. Пересылаются без ошибок UDP пакеты, длина которых не превышает 1136 байт с учётом заголовка. Пакеты большей длины обрезаются, а UDP CRC становится равной нулю. Мне для совместимости с предыдущей версией нужен пакет длиной 1480. Можно в lwip увеличить максимальную длину пакета? И какой параметр за это отвечает?
2. Мне нужен поток данных 25-30 Мбит в секунду. Достижимо ли это с lwip? Как оптимизировать процесс передачи данных? Насколько я понял, функция pbuf_take просто копирует (программно) данные из моего буфера в промежуточный буфер, снабженный заголовками UDP, IP и Ethernet. Если сформировать эти заголовки самостоятельно, то может при простой отправке UDP можно и без LWIP обойтись? Оставить ему ARP и DHCP?
Заранее спасибо за любую инфу по этой теме.

Похоже на второй вопрос частично сам могу ответить. По крайней мере это легко проверить.  Очень вероятно, что можно выделить статический буфер с учётом длины заголовков. А udp_sendto сформирует заголовки и отправит пакет прямо из моего буфера. Только надо разобраться, как определить, что текущая операция передачи пакета завершена.

Share this post


Link to post
Share on other sites

On 9/16/2022 at 1:22 PM, amiller said:

p_udp = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_POOL);
err = pbuf_take(p_udp, &buff, size);
err = udp_sendto(pcb, p_udp, &client, udp_d_port);

......


2. Мне нужен поток данных 25-30 Мбит в секунду. Достижимо ли это с lwip? Как оптимизировать процесс передачи данных? Насколько я понял, функция pbuf_take просто копирует (программно) данные из моего буфера в промежуточный буфер, снабженный заголовками UDP, IP и Ethernet. Если сформировать эти заголовки самостоятельно, то может при простой отправке UDP можно и без LWIP обойтись? Оставить ему ARP и DHCP?
Заранее спасибо за любую инфу по этой теме.

Похоже на второй вопрос частично сам могу ответить. По крайней мере это легко проверить.  Очень вероятно, что можно выделить статический буфер с учётом длины заголовков. А udp_sendto сформирует заголовки и отправит пакет прямо из моего буфера.

Лично я никогда не использовал функцию pbuf_take, т.е. аллокация, отправка, освобождение.

Если вы не используете RTOS и функция отправки пакетов у вас блокирующая и если вы всегда отправляете пакеты одного размера, то можно немного сэкономить времени на аллокации и освобождении.

Сразу выделить память  p_udp = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_POOL); и все время ее использовать. И p_udp будет вашим статическим буфером.

И писать ваши данный сразу в p_upd->payload.

On 9/16/2022 at 1:22 PM, amiller said:

Только надо разобраться, как определить, что текущая операция передачи пакета завершена.

А как у вас отправляются пакеты - смотрите реализацию функции low_level_output в файле ethernetif.c

И скорее всего, даже наверняка, функция сама ждет завершения отправки. И пока не отправит, то не выйдет из нее.

Share this post


Link to post
Share on other sites

В 16.09.2022 в 13:22, amiller сказал:

2. Мне нужен поток данных 25-30 Мбит в секунду. Достижимо ли это с lwip? Как оптимизировать процесс передачи данных? Насколько я понял, функция pbuf_take просто копирует (программно) данные из моего буфера в промежуточный буфер, снабженный заголовками UDP, IP и Ethernet. Если сформировать эти заголовки самостоятельно, то может при простой отправке UDP можно и без LWIP обойтись? Оставить ему ARP и DHCP?

Не знаю как в lwip и как дело обстоит конкретно в вашем МК, но обычно Ethernet-блок имеет DMA-транспорт для приёма/передачи Ethernet-кадров в/из ОЗУ. Частенько этот транспорт работает только с определённым регионом ОЗУ МК (не любое место ОЗУ допустимо). Если расположить буферы формируемых на передачу Ethernet-кадров в этом регионе, то можно формировать их прямо "по месту", внутри буфера. Тогда не нужны будут дополнительные копирования память-память. И готовый кадр будет забирать уже DMA (при старте его передачи Ethernet-блоком).

В своём TCP-стеке я именно так и поступаю: исходящие кадры формирую прямо в Ethernet-ОЗУ, без промежуточных копирований. Естественно - никаких куч, дин.памяти и прочей ненужной требухи. В Ethernet-ОЗУ декларирован массив кадров, заполняемых по мере надобности. По заполнении очередного свободного кадра из массива, его дескриптор ставится на цепочку передающего FIFO. В ISR завершения передачи кадра, этот кадр метится как свободный и доступный для заполнения новым кадром. Процесс заполнения и передачи идёт параллельно: пока предыдущие кадры стоят в передающей очереди и передаются Ethernet-блоком, в это время следующие кадры заполняются/формируются процессором.

Так можно достигнуть макс.производительности. Но для этого вам скорее всего придётся самостоятельно детально изучить Ethernet-периферию. Не полагаясь на lwip.

 

PS: Почему на lwip свет клином сошёлся? Можно ведь свой стек написать. Или можно использовать более лёгкие готовые стеки (например uIP).

Share this post


Link to post
Share on other sites

On 9/16/2022 at 6:25 PM, jcxz said:

Не знаю как в lwip и как дело обстоит конкретно в вашем МК, но обычно Ethernet-блок имеет DMA-транспорт для приёма/передачи Ethernet-кадров в/из ОЗУ. Частенько этот транспорт работает только с определённым регионом ОЗУ МК (не любое место ОЗУ допустимо). Если расположить буферы формируемых на передачу Ethernet-кадров в этом регионе, то можно формировать их прямо "по месту", внутри буфера. Тогда не нужны будут дополнительные копирования память-память. И готовый кадр будет забирать уже DMA (при старте его передачи Ethernet-блоком).

В своём TCP-стеке я именно так и поступаю: исходящие кадры формирую прямо в Ethernet-ОЗУ, без промежуточных копирований. Естественно - никаких куч, дин.памяти и прочей ненужной требухи. В Ethernet-ОЗУ декларирован массив кадров, заполняемых по мере надобности. По заполнении очередного свободного кадра из массива, его дескриптор ставится на цепочку передающего FIFO. В ISR завершения передачи кадра, этот кадр метится как свободный и доступный для заполнения новым кадром. Процесс заполнения и передачи идёт параллельно: пока предыдущие кадры стоят в передающей очереди и передаются Ethernet-блоком, в это время следующие кадры заполняются/формируются процессором.

Так можно достигнуть макс.производительности. Но для этого вам скорее всего придётся самостоятельно детально изучить Ethernet-периферию. Не полагаясь на lwip.

 

PS: Почему на lwip свет клином сошёлся? Можно ведь свой стек написать. Или можно использовать более лёгкие готовые стеки (например uIP).

Спасибо, именно в эту сторону я двигаюсь. Предыдущая версия устройства у меня была с внешним контроллером W5100. Там необходимые элементы стека были реализованы ручками. По крайней мере UDP передача и DHCP клиент.
Лишние копирования информации уже исключил. Сейчас планирую изучить взаимодействие lwip с ethernet периферией и вернуться к самостоятельной реализации стека.

Share this post


Link to post
Share on other sites

6 часов назад, amiller сказал:

Сейчас планирую изучить взаимодействие lwip с ethernet периферией и вернуться к самостоятельной реализации стека.

А lwip в этом процессе - зачем? Неужто у вашего МК отсутствует мануал, описывающий Ethernet-периферию?   :umnik2:

Share this post


Link to post
Share on other sites

13 hours ago, jcxz said:

А lwip в этом процессе - зачем? Неужто у вашего МК отсутствует мануал, описывающий Ethernet-периферию?   :umnik2:

Да всё достаточно просто. Посчитал, что освоение Etрernet периферии с нуля достаточно сложный процесс.
Предполагал, что сгенерирую пример Кубом, разберусь и адаптирую под себя.
Но ни одна из нескольких попыток использования Куба для формирования модуля связи не увенчалась успехом.
Потом пробовал несколько "рабочих" примеров из интернета, настраивал ноги физики под себя и пытался запустить.
Один простой пример заработал криво-косо.
Далее долго вычищал из него кубовский мусор, поженил со своим софтом.
Сейчас всё работает. Понятно, что lwip избыточен для моих задач, да и вносит свою долю неопределенности в надежность.
Поэтому следующий шаг - постепенно перейти на свою понятную реализацию стека.
Мне нужно то от стека очень немного.

 

Share this post


Link to post
Share on other sites

В процессе оптимизации софта обнаружил в регистре ETH->MACCR интересный бит ARPEN (STM32H743ZIT6).
Описание достаточно краткое, но  судя по всему этот бит включает автоматический ответ на ARP запросы на уровне MAC ETH модуля.
Если я правильно понял описание, если IP адрес из ARP запроса совпадает с регистром ETH->MACARPAR, то контроллер автоматически отвечает, подставляя в ответ MAC адрес из регистра ETH->MACA3R.
Проблема возникла в записи любого числа в регистр ETH->MACARPAR. Не могу это сделать и программно и в отладчике.
Гугл находит только один вопрос на эту тему, но без ответа.
https://community.st.com/s/question/0D50X0000BAEwqMSQT/enable-arp-offload-on-stm32h753
Кто нибудь пробовал запустить этот сервис? Получилось?

Share this post


Link to post
Share on other sites

On 9/27/2022 at 7:39 AM, amiller said:

В процессе оптимизации софта обнаружил в регистре ETH->MACCR интересный бит ARPEN (STM32H743ZIT6).

А вы Errata почитайте.

Share this post


Link to post
Share on other sites

10 minutes ago, dimka76 said:

А вы Errata почитайте.

Спасибо, всегда забываю про эту часть документации...
Действительно в Errata есть такой пункт: "ARP offload function not effective"
Только в качестве причины указана другая проблема, до которой я ещё не дошёл.
А проблема с записью в регистр ETH->MACARPAR никак не поясняется.
Тем не менее вопрос потерял смысл, надо ARP запросы парсить программно.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...