Jump to content

    
BorisBritwa

STM32F7LWIP

Recommended Posts

Плата NUCLEO stm32f767ZI .

Задача передать поток с камеры ov2640 2-10Мегабит. Делал такое уже на w5500 и stm32f4.

Сейчас разогнал мк

В кубе включил TCM interface для flash.ART Accelerator,instruction perfetch настройки адреса flash изменил вручную, т.к. куб не прописывает для KEIL почему то.Потребление камня заметно возросло производительность тоже.
Использую DMA (для DСMI) оно вроде как и FLASH( по умолчанию) работает через шину AHB->AXI и там вроде как могут пробыть проблемы если включить кэш команд и данных.Поэтому сделал как написал выше.

В планах разместись стек и кучу и FIFO буфер в DTCM и обработчики прерываний в ITCM.

Работаю без RTOS RAW API.Проблема в том, ЧТО Я НЕ МОГУ ПОЛУЧИТЬ нормальные 10 Мегабит не говоря уже о 10 Мегабайтах в секунду о которых пишут.

Передаю пакеты размером 16Кило след. образом.
while(ETH_TXBUF_SIZE > get_tcp_sndbuf_free(&CI))
   MX_LWIP_Process();
tcp_write(CI.tcp_client_pcb,ETH_TX_buf,ETH_TXBUF_SIZE, 1);                            
tcp_output(CI.tcp_client_pcb);   

Проблема в том что пришлось выкрутить TCP_TMR_INTERVAL  в 1 вместо 250? Иначе не работает на таких скоростях.

По идее TCP_TMR_INTERVAL я вообще не должен трогать!!!

Сейчас удается передать поток 5 Мегабит с камеры, есть tcp retransmission,tcp dup ACK.

Есть логи отладки через stats_display(); там все ОК.

 

 

lwipopts.h

Edited by BorisBritwa

Share this post


Link to post
Share on other sites

С 7xx не работаю, ничего конкретного подсказать не могу. Посмотрите это письмо из рассылки lwip, возможно найдете что-то полезное в вашем случае.

И как модератор предупреждаю вас: прекратите совать свои видео в каждое сообщение, это будет расценено как навязчивая реклама (канала) с соответствующими оргвыводами. При регистрации вы согласились соблюдать Правила форума, прочитайте еще раз пункт 3.6. На первый раз устное предупреждение.

Share this post


Link to post
Share on other sites

Также читал

       __DSB у меня такой строчки нет, и ее добавление ничего не решает в моем случае.

Вернулся к истокам.Собрал дефолтный проект с lwip и больше ничего, изменил MEM_SIZE 65536,MEMP_NUM_TCP_SEG 401,TCP_SND_BUF 53600.

КЭШ НЕ ВКЛЮЧАЛ.Передаю рас в секунду массив размером 16Кило.Передача идет но в wireshark много TCP_DUP_ACK,TCP_retransmission,

 

  while (1)
  {
		MX_LWIP_Process();
		time_ms = HAL_GetTick();
		if(time_ms - last_time_ms_task1 > 1000){//TCP_TMR_INTERVAL 
			send_buf_frspace = get_tcp_sndbuf_free(&CI);
			printf("send_buf_frspace %d\n\r",send_buf_frspace);
			if (CI.conn_status == S_ESTABLISHED)
				if(ETH_TXBUF_SIZE < send_buf_frspace){
					ret_err = tcp_write(CI.tcp_client_pcb,ETH_TX_buf,ETH_TXBUF_SIZE, 1);							
					if(ret_err != ERR_OK)printf("tcp_write err %d\n\r",ret_err);
					ret_err = tcp_output(CI.tcp_client_pcb);
					if(ret_err != ERR_OK)printf("tcp_output err %d\n\r",ret_err);
				}
		 last_time_ms_task1 = time_ms;
		}
    
  }

валит ошибки ERR_USE после вызова tcp_output();

Причина ошибки файл ethernetif.c, тут функция low_level_output().

        /* Check if the buffer is available */
        if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
        {
          errval = ERR_USE;
          goto error;
        }

 

 

Share this post


Link to post
Share on other sites

У меня подозрение на малое количество буферов для передачи.

Плюс, в Вашем конфиге:

#define TCP_WND 4096 - Размер TCP Окна - всего 4кБ. Это мало. Выставьте хотя бы в 32к. Но возможно дело не в нём.

#define MEMP_NUM_PBUF 32 - Подозреваю, что количество буферов (хотя могу ошибиться) - всего 32. Тоже мало. Поднимите хотя бы до 60 (по рекомендации авторов LWIP: http://www.nongnu.org/lwip/2_0_x/group__lwip__opts__memp.html#ga92b30aed958ec59334d936d4ca725418 ). Судя по выделеным под буфер 132кБ, должно влезть вплоть до 86. Возможно чуть меньше из-за накладных расходов от DMA контроллера.

 

Как-то пробовал гонять поток данных (разве что по UDP от железки в сторону компа) и обратно (от компа к железке, но уже по TCP) через tlk105 (mii ethernet физика), так скорость в первом случае упёрлась в потолок (~99Мбит/с), а во втором - была порядка 40Мбит/с. Дамп трафика, к сожалению, не найти.

Share this post


Link to post
Share on other sites
12 минут назад, AlanDrakes сказал:

У меня подозрение на малое количество буферов для передачи.

Плюс, в Вашем конфиге:

#define TCP_WND 4096 - Размер TCP Окна - всего 4кБ. Это мало. Выставьте хотя бы в 32к. Но возможно дело не в нём.

#define MEMP_NUM_PBUF 32 - Подозреваю, что количество буферов (хотя могу ошибиться) - всего 32. Тоже мало. Поднимите хотя бы до 60 (по рекомендации авторов LWIP: http://www.nongnu.org/lwip/2_0_x/group__lwip__opts__memp.html#ga92b30aed958ec59334d936d4ca725418 ). Судя по выделеным под буфер 132кБ, должно влезть вплоть до 86. Возможно чуть меньше из-за накладных расходов от DMA контроллера.

 

Как-то пробовал гонять поток данных (разве что по UDP от железки в сторону компа) и обратно (от компа к железке, но уже по TCP) через tlk105 (mii ethernet физика), так скорость в первом случае упёрлась в потолок (~99Мбит/с), а во втором - была порядка 40Мбит/с. Дамп трафика, к сожалению, не найти.

По буферам запас было видно из статистики,  кроме TCP_SND_BUF, иногда не хватает.

Сейчас все на минимуме, рас в секунду 16 кило.Проект собрал заново без использования другой периферии ethernet +usart для отладки(скорость 2000000). Размер окна TCP_WND, только на прием будет влиять? Во всяком, ставил больше изменений не видно было. MEMP_NUM_PBUF в порог не упирался  исходя из статистики.

Share this post


Link to post
Share on other sites

Прилепляю лог статистики для нового чистого проекта только с lwip отправка рас в секунду 16 кило, как отправляю указал выше.Есть ошибки ERR_USE после вызова tcp_output();  в текстовом файле они можно найти по строке "tcp_output err -8". Кэш  пока не использую, могу скинуть проект если кому это поможет.Пакеты передаются но много ошибок писал выше.

Ошибки ERR_USE появляются в функции  low_level_output() находится в файле  ethernetif.c строки  :

      /* Is this buffer available? If not, goto error */
      if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
      {
        errval = ERR_USE;
        goto error;
      }

 Данная проблема уже давно https://community.st.com/s/question/0D50X00009Xkgff/stm32f746-ethernet-dma-transmit-problem

statistic.txt

Share this post


Link to post
Share on other sites

НАДЕЮСЬ ЭТО СЭКОНОМИТ КОМУ-ТО ВРЕМЯ.МОИ НАБЛЮДЕНИЯ

РАЗМЕР СООБЩЕНИЯ  КРАТЕН MSS, если одна посылка то <=MSS. РАЗМЕР ОТПРАВЛЯЕМОГО ПАКЕТА НЕ БОЛЕЕ 6*MSS . Кэш не включен MSS1460 куча 60 кило,размер TSP_SND_BUF 60*MSS удается прокачивать до 6 мегабит без ошибок, частота SYSCLK 96MHZ,  уменьшал до 10 TCP_TMR_INTERVAL, быстрее буфер освобождается. Можно не уменьшать но буфер тогда надо по шире.

В логах статистики запас по буферам и памяти не придраться.Кроме TCP_SND_BUF при ошибках его будет ужирать. ETH_TX_buf его размер меняется и указан в функции "отправки",правильнее сказать функции записи в другой буфер, под который предварительно выделяется память.И после каждой tcp_write() вызывается tcp_output() как выше писал.Настройки lwip прилагаю.

Например отправляю рас в 500мс буфер отправки TCP_SND_BUF свободен на 80% :

tcp_write(CI.tcp_client_pcb,ETH_TX_buf,1460*6, 1); будет работать без ошибок MSS 1460

tcp_write(CI.tcp_client_pcb,ETH_TX_buf,1500*6, 1); будет работать c ошибками. ERR_USE  и повторные отправки

tcp_write(CI.tcp_client_pcb,ETH_TX_buf,1460*7, 1);будет работать c ошибками.ERR_USE и повторные отправки

tcp_write(CI.tcp_client_pcb,ETH_TX_buf,1460*8, 1);будет работать c ошибками.ERR_USE  после вызова tcp_output() повторных оправок нет, но если увеличить скорость передачи думаю появятся .

Если включить ART и изменить адрес как выше писал, то опять ошибки при передаче.Если не включать ART поднять частоту выше 216MHZ  опять ERR_USE  и повторные отправки.Короче одно шайтнство.Корень проблемы указан выше и где он возникает,но решают его каждый по разному .

 

Сейчас добавлю еще работу с DMA и все по хер...ся.

lwipopt.txt

Edited by BorisBritwa

Share this post


Link to post
Share on other sites
2 часа назад, BorisBritwa сказал:

tcp_write(CI.tcp_client_pcb,ETH_TX_buf,1460*6, 1); будет работать без ошибок MSS 1460

tcp_write(CI.tcp_client_pcb,ETH_TX_buf,1500*6, 1); будет работать c ошибками. ERR_USE  и повторные отправки

Я б на вашем месте сначала добился безошибочной передачи и приема сырых езернет пакетов между двумя платами аля-пин-понг на максимальной скорости, потом бы прикрутил стек и пошел дальше...

Edited by mantech

Share this post


Link to post
Share on other sites

О, и кстати, проверьте, что все буферы, которые используются Ethernet DMA выравнены на 4 байта (можно больше).

Один раз я пару дней ловил непонятную ошибку с приёмом данных и зависанием работы на приём по той же причине - дескриптор буфера оказывался недоступен для DMA контроллера. Выяснилось, что если память не была выравнена, то запись происходила в дополнительные места вокругу порции данных. Примерно так:

Буфер (16 байт), в памяти с адреса xxx01 вместо xxx00:
Адрес:
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10- 11- 12- 13- 14- 15- 16
Данные:
x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x
 Происходит запись 4 байт (01, 02, 04, 08) в адреса 1-4:
Адрес:
0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10- 11- 12- 13- 14- 15- 16
Данные:
00- 01- 02- 04- 08- 00- 00- 00- x - x - x - x - x - x - x - x - x
Следующая запись 4 байт (10, 20, 40, 80) в адреса 4-8:
Адрес:
0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10- 11- 12- 13- 14- 15- 16
Данные:
00- 01- 02- 04- 08- 10- 20- 40- 80- 00- 00- 00- x - x - x - x - x

С заким описанием буфера - заработало без ошибок:

uint8_t TX_BUF[ETH_MAX_PACKET_SIZE * BUFFERS_COUNT] __attribute__((aligned(4)));

Собиралось НЕ под LWIP, а под чуть более голое железо.

Share this post


Link to post
Share on other sites
11 минут назад, AlanDrakes сказал:

О, и кстати, проверьте, что все буферы, которые используются Ethernet DMA выравнены на 4 байта (можно больше).

Один раз я пару дней ловил непонятную ошибку с приёмом данных и зависанием работы на приём по той же причине - дескриптор буфера оказывался недоступен для DMA контроллера. Выяснилось, что если память не была выравнена, то запись происходила в дополнительные места вокруг порции данных. Примерно так:

С таким описанием буфера - заработало без ошибок:

uint8_t TX_BUF[ETH_MAX_PACKET_SIZE * BUFFERS_COUNT] __attribute__((aligned(4)));

Собиралось НЕ под LWIP, а под чуть более голое железо.

Спасибо буду иметь ввиду.

 Не написал, что кэши и кучу поднимал аж до 0x4000(которые в startup, сейчас 0x1000) для lwip памяти давал за 100К результата ноль.

Пока вопрос  почему так происходит открыт, но уже можно с этим жить.Сейчас буфер кратен MSS*10.Удалось до 5 мегабит поднять, пока хватит можно стримить. На wiznet w5500 и F4 мне не удалось добиться такой скорости.Там либо SPI медленный,вешаешь на другой канал spi уже быстрый, так уже задействовано одно и тоже ДМА с разными "каналами" и по скорости хуже получается.То есть одно ДМА обслуживает и SPI и DCMI.

 

В итоге на F7 SYSCLK 96MHZ ,если установить в два раза выше то появятся ошибки при передаче( опять дескриптор будет, будет не доступен для ДМА, когда ему вздумается) если их не было.

Сейчас задействовано еще одно DMA DCMI, получаю 15 FPS 480x320, c OV2640 в норм качестве, по TCP.Ошибок при вызове функций нет.Если смотреть в wire shark, то не значительно на основном фоне ретрансмиты и dup_ack.

 

 

Share this post


Link to post
Share on other sites

Есть у меня подозрение, что 96МГц маловато для этого кристалла, или этой задачи.

Особенно, имея два активных канала DMA. Ощущаю возможные попытки одновременного доступа к памяти, что черевато задержками и не совсем сбоями, но всё же.

Можете описать процесс стриминга на примере нескольких кадров?

Примерно так:

1. Получаем кадр из камеры через DMAxxx, кладём его по адресу 0x20xxxxxx

2. Канал DMAyyy настраиваем на (%действие%) (адрес?)

3. Собираем пакет в адресах 0x2xxxxxxx

<...>

И так далее. Это может помочь в понимании, может ли действительно быть борьба за шину памяти.

 

Кстати, посмотрите распределение адресов для разных DMA и разных ведомых на своём контроллере. Если ядро активно что-то делает, то оно будет чаще выигрывать арбитраж шины и тормозить всех остальных. В этом случае - либо отправлять его в WFI/WFE паузы, либо как-то иначе настраивать адресацию. Ну или проще - задрать тактовую частоту выше.

Share this post


Link to post
Share on other sites

В итоге перешел на RTOS+LWIP проблем никаких нет.Проц на максимальной частоте.Кэш выключен.TCM INTERFACE+ART+PRETHETCH скорость передачи по TCP до 14 Мегабит.Если как у меня на полную используется DMA DCMI, то скорость передачи до 12 мегабит больше пока не удалось получить(ну я сильно не старался).Не замерял какая скорость передачи у ESP32CAM, вблизи точки доступа было бы интересно сравнить.

Share this post


Link to post
Share on other sites
3 hours ago, BorisBritwa said:

В итоге перешел на RTOS+LWIP проблем никаких нет.Проц на максимальной частоте.Кэш выключен.TCM INTERFACE+ART+PRETHETCH скорость передачи по TCP до 14 Мегабит.Если как у меня на полную используется DMA DCMI, то скорость передачи до 12 мегабит больше пока не удалось получить(ну я сильно не старался).Не замерял какая скорость передачи у ESP32CAM, вблизи точки доступа было бы интересно сравнить.

Отлично ! Ждём на github для тестирования.

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.