Dec_NN 0 20 декабря, 2021 Опубликовано 20 декабря, 2021 · Жалоба STM32F7 (RAM: 512Кбайт). Среда CubeIDE. Есть функция в которой принятые UDP пакеты складываются в кольцевые буферы. Буферы - это глобальный трехмерный массив: udp_rxbuf[snum][128][256], где snum - количество сокетов. Т.е. для каждого сокета можно сохранить до 128 пакетов по 256 байт. При количестве сокетов до 3-х все работает корректно. Как только увеличиваю размер массива до работы с 4-мя сокетами (snum=4), все ломается. Работа с сокетами происходит следующим образом: Есть таймер. В его обработчике прерывания вызываются функции: ethernetif_input(&gnetif); sys_check_timeouts(); При получении udp пакета программа прыгает в в связанную с сокетом функцию void udp_receive_handler(void *arg, struct udp_pcb *upcb, struct pbuf *p, const struct ip4_addr *addr, u16_t port), где полученный пакет укладывается в буффер. Хотя массив буферов и большой - 160 кбайт, но линкер показывает, что памяти RAM еще вполне достаточно, больше половины свободно. Понимаю, что где то, что то нехватает, или что то на что то налазиет, но не знаю что. Т.к. данный массив глобальный, он ведь никак не должен забивать стек, но что то происходит и все ломается. Подскажите, что я делаю не так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dec_NN 0 20 декабря, 2021 Опубликовано 20 декабря, 2021 · Жалоба Похоже затыкается LWIP. А именно в файле stm32f7xx_hal_eth.c условие /* Check if segment is not owned by DMA */ if(((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET)) никогда не срабатывает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
viakon 0 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба В чем затык то? Перестает МАС принимать пакеты? Перестает вызываться udp_receive_handler? Может приходит два пакета, а ваша программа воспринимает их как один? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 1. Не жирно ли вызывать ethernetif_input() в прерывании? 2. udp_rxbuf находится в одном физическом регионе ОЗУ? 3. Корректно ли обрабатываются буферы совместно с L1? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dec_NN 0 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 42 minutes ago, Arlleex said: 1. Не жирно ли вызывать ethernetif_input() в прерывании? А каким образом тогда обеспечить регулярную проверку входящих пакетов? В основном цикле с необходимой частотой этого не сделать. Quote 2. udp_rxbuf находится в одном физическом регионе ОЗУ? 3. Корректно ли обрабатываются буферы совместно с L1? Здесь я, к сожалению, не совсем понимаю о чем речь. 56 minutes ago, viakon said: В чем затык то? Перестает МАС принимать пакеты? Перестает вызываться udp_receive_handler? Может приходит два пакета, а ваша программа воспринимает их как один? Не заходит в udp_receive handler по причине того, что не проходит условие в строчке указанной выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
viakon 0 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 5 минут назад, Dec_NN сказал: А каким образом тогда обеспечить регулярную проверку входящих пакетов? В основном цикле с необходимой частотой этого не сделать. В прерывании (ETH_IRQHandler) по окончании DMA обмена с MAC выставить флажочек. В основном цикле проверять этот флаг и по появлении вызывать ethernetif_input. void ETH_IRQHandler(void) { ETH_receive_pack = 1; // сброс Eth DMA Rx IT pending флагов ETH_DMAClearITPendingBit(ETH_DMA_IT_R); ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS); } в основном цикле так if(ETH_receive_pack) { ETH_receive_pack = 0; /* Handles all the received frames */ while(ETH_GetRxPktSize() != 0) { LwIP_Pkt_Handle(); } } void LwIP_Pkt_Handle(void) { /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */ ethernetif_input(&netif); } Работает еще со времен до HAL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dec_NN 0 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 40 minutes ago, viakon said: В прерывании (ETH_IRQHandler) по окончании DMA обмена с MAC выставить флажочек. В основном цикле проверять этот флаг и по появлении вызывать ethernetif_input. Я пробовал делать похожим образом, но дело в том, что в основном цикле есть куски надолго блокирующие выполнение кода. Например функция вывода статистики в консоль и т.д. и пока дело дойдет до проверки флага, часть пакетов просто теряется. Поэтому решил сделать прерывание по таймеру, чтобы гарантированно забирать пришедшие пакеты. Upd: Сейчас попробовал убрать прерывание и делать вызов ethernetif_input() из основного цикла. Ничего не изменилось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 2 часа назад, Dec_NN сказал: Я пробовал делать похожим образом, но дело в том, что в основном цикле есть куски надолго блокирующие выполнение кода. Очевидно - давно пора было научиться работать под РТОС. Уже M7, а до сих пор ездиете на телеге супер-лупе.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dec_NN 0 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 1 hour ago, jcxz said: Очевидно - давно пора было научиться работать под РТОС. Уже M7, а до сих пор ездиете на телеге супер-лупе.... Это первый ARM с которым работаю, так уж досталось по наследству, и опыта работы с ними нет. RTOS обязательно буду осваивать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 45 минут назад, Dec_NN сказал: Это первый ARM с которым работаю, так уж досталось по наследству, и опыта работы с ними нет. RTOS обязательно буду осваивать. Под РТОС просто разносите в разные задачи код, имеющий "надолго блокирующие куски" и код работающий с потоком UDP-кадров. Задаче, работающей с UDP-кадрами, даёте бОльший приоритет. И дело в шляпе. PS: Подозреваю, что тогда и не понадобятся такие дикие массивы по 128 UDP-кадров. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 21 декабря, 2021 Опубликовано 21 декабря, 2021 · Жалоба 10 часов назад, Dec_NN сказал: А каким образом тогда обеспечить регулярную проверку входящих пакетов? В основном цикле с необходимой частотой этого не сделать... Как отметили уже выше, например, разрабатывая на базе RTOS. Она не кусается, ресурсы почти не потребляет. Цитата Здесь я, к сожалению, не совсем понимаю о чем речь... Вы взяли МК с полноценным аппаратным L1-кэшем внутри. Вот и вопрос - драйвер в курсе, что он написан под STM32F7? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dec_NN 0 22 декабря, 2021 Опубликовано 22 декабря, 2021 · Жалоба Отключил DCache. Все стало работать. Почему включение кеша данных вызывает мою проблему пока не понимаю. Буду разбираться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 22 декабря, 2021 Опубликовано 22 декабря, 2021 · Жалоба 1 hour ago, Dec_NN said: Отключил DCache. Все стало работать. Почему включение кеша данных вызывает мою проблему пока не понимаю. Буду разбираться. Потому что ядро работает в Кэшем, а периферия с ОЗУ. Вам надо либо отключить Кэшь не для всего ОЗУ, а для вашего буфера udp_rxbuf[snum][128][256], либо вызывать SCB_InvalidateCash после записи данных в ваш буфер udp_rxbuf[snum][128][256]. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 22 декабря, 2021 Опубликовано 22 декабря, 2021 · Жалоба 1 час назад, Dec_NN сказал: Почему включение кеша данных вызывает мою проблему пока не понимаю. Буду разбираться Гляньте сюда. Там собраны основные проблемы с драйверами эзернета из куба. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться