|
|
  |
lwIP: уведомление об изменении статуса линка, стек не заводится, если изначально не подключен кабель |
|
|
|
Feb 7 2017, 11:44
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 6-01-09
Пользователь №: 42 957

|
Здравствуйте! Курю примеры реализаций lwIP под FreeRTOS от STM32 и CubeMX. Но во всех примерах общая проблема: если Ethernet кабель изначально отключен на запуске системы, то после его подключения всё равно ничего не работает. Вопрос. Допустим, прерывание об изменении физики получено; а что собственно в нём делать? Как уведомить стек об изменении статуса связи. чтобы он перезапустил процедуру назначения IP-адреса от DHCP, и что там ещё надо. Вот это с первого раза ни к чему не привело, что-то не так делаю или надо что-то ещё? Код if (netif_is_link_up(&gnetif)) { /* When the netif is fully configured this function must be called */ netif_set_up(&gnetif); } else { /* When the netif link is down this function must be called */ netif_set_down(&gnetif); }
Сообщение отредактировал IgorKossak - Feb 8 2017, 20:09
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Feb 8 2017, 04:46
|
Местный
  
Группа: Участник
Сообщений: 290
Регистрация: 9-12-05
Из: г. Пермь
Пользователь №: 12 002

|
Цитата(Сергей Борщ @ Feb 7 2017, 17:35)  Я делаю netif_set_link_up(&NetIF)/netif_set_link_down(&NetIF). Но не в прерывании, а в потоке. Кроме того, в настройках есть #define LWIP_DHCP_CHECK_LINK_UP, поставьте его в нужное состояние. Использую версию 2.0.2, что было в более ранних - не знаю. Как обрабатываете, если сетка 100мбит сменилать на 10мбит (пользователь выдернул шнурок из одного хаба и воткнул в другой)? Я эту проблему решил пока перезагрузкой.
|
|
|
|
|
Feb 8 2017, 11:20
|
Местный
  
Группа: Участник
Сообщений: 290
Регистрация: 9-12-05
Из: г. Пермь
Пользователь №: 12 002

|
Цитата(Сергей Борщ @ Feb 8 2017, 11:41)  Вычитываю информацию из физики и пихаю в ETH->MACCR. Проверить не было возможности - у меня нет 10-Мбитных сосков вокруг. Но в описании запрета на запись в ETH->MACCR во время работы не нашел, значит можно. netif_set_link_down ETH->MACCR netif_set_link_up Так?
|
|
|
|
|
Feb 8 2017, 11:38
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (viakon @ Feb 8 2017, 13:20)  Так? Без первой строчки. Ибо если линк разорван, то что писать в ETH->MACCR? А если он уже установлен, то и меняться там нечему. В обработчике прерывания физики по флагу Autonegotiation complete пишу MACCR, ставлю флаг "связь есть", разрешаю прерывание физики по флагу Link down. При получении прерывания Link down сбрасываю флаг "связь есть" и разрешаю прерывание Autonegotiation complete. В основном цикле при изменении флага "связь есть" делаю netif_set_link_up() или netif_set_link_down().
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 10 2017, 06:17
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 6-01-09
Пользователь №: 42 957

|
Здравствуйте. Проблема временно решена следующим образом. Заведён выход прерывания, и DP83848 настроена на выдачу прерывания по изменению статуса линка. Но само прерывание не подключено, вместо этого в одном из потоков несколько раз в секунду вызывается следующая штука: CODE #define PHY_MISR 0x12 #define PHY_SR 0x10 #define PHY_LINK_STATUS 0x0001
// Poll PHY Interrupt Output if (0==HAL_GPIO_ReadPin(Выход прерывания)) { uint32_t regvalue=0; HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, ®value); // Clears PHY intterrupt output HAL_ETH_ReadPHYRegister(&heth, PHY_SR, ®value); // Get Link Status bool linkup=!!(regvalue & PHY_LINK_STATUS);
if (linkup) { netif_set_link_up(&gnetif); } else { netif_set_link_down(&gnetif); }; // linkup if (netif_is_link_up(&gnetif)) { netif_set_up(&gnetif); } else { netif_set_down(&gnetif); }; // netif_is_link_up ethernetif_update_config(&gnetif); };
Всё ли здесь на вашэкспертный взгляд правильно и существуют ли другие решения ? И второй момент. Судя по форуму, у многихэкспертов в подобных реализациях Ethernet часто и беспричинно подыхает. У меня, например, начал подыхать как только дело дошло до тестов на производительность. Вопрос: все эти стеки вообще отлажены? Или единственный выход - писать свои? В частности, мой механизм подыхания изображён на картинке.
Сообщение отредактировал IgorKossak - Feb 10 2017, 09:47
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!!
|
|
|
|
|
Feb 12 2017, 11:37
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 6-01-09
Пользователь №: 42 957

|
Здравствуйте ещё раз. Был опыт применения LwIP-стека на отладочной плате STM32F746-Discovery. И вот что выяснилось.
Если в настройках процессорного ядра включены кеши инструкций и данных, то LwIP-стек работает только при 0-м уровне оптимизации кода (-o0). Как только захочешь включить люьорй другой уровень оптимизации, он перестаёт ра6отать.
Если же кеши выключены, то для работы стека требуется другое странное условие (выяснилось методом тыка путём сравнения Cube-generated проекта с другим рабтающим проектом демонстрационного веб-сервера от ST). Буферы DMA приёма-передачи Ethernet (там их аж 4 штуки) должны быть расположены в первых 64 килобайтах оперативной памяти, которая у этого контроллера помечена как какая-то особая TCM-память (Tightly-Coupled Memory). Если при расширении и усложнении проекта эти буферы уползают в другое место, то стек перестаёт работать.
В википедии написано, что после завершения любой операции с DMA, перед тем как полученные данные потребуются в программе, нужно вставлять барьеры синхронизации. но я так полагаю, в LwIP-стеке их конечно же нет: STM32F746 - один из последних, самых мощных камней, некоторые особенности которого уже вкрывают границу применимости стека, не отлаженного под такие мощные процессоры. Ведь вполне могло оказаться и то, что из этой особой TCM-памяти кеши быстрее прогружаются.
Итого, у меня на этом камне LwIP-стек переставал ра6отать сходу при сочетании каких-то странных условий. До тестов на производительность/устройчивость дело даже не дошло. Судя по форуму, у других эксперотов этот стек перестаёт ра6отать, как только дело доходит до этих тестов. Вопрос: есть ли другие, надёжные стеки? Или коммерческие организации в основном пишут свои?
|
|
|
|
|
Feb 12 2017, 14:47
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Как минимум, в нужных местах кода необходимо вызывать функции управление кэш-памятью: Код // Сейчас в эту память будем читать по DMA // Убрать копию этой области из кэша void arm_hardware_invalidate(unsigned long base, size_t size) { SCB_InvalidateDCache_by_Addr((void *) base, size); // DCIMVAC register used. }
// Сейчас эта память будет записываться по DMA куда-то // Записать содержимое кэша данных в память void arm_hardware_flush(unsigned long base, size_t size) { SCB_CleanDCache_by_Addr((void *) base, size); // DCCMVAC register used. }
// Сейчас эта память будет записываться по DMA куда-то. Потом содержимое не требуется // Записать содержимое кэша данных в память // Убрать копию этой области из кэша void arm_hardware_flush_invalidate(unsigned long base, size_t size) { SCB_CleanInvalidateDCache_by_Addr((void *) base, size); // DCCIMVAC register used. } Функция __DSB() не поможет. Кстати, при инициализации не забыть включить Код SCB_InvalidateICache(); SCB_EnableICache();
SCB_InvalidateDCache(); SCB_EnableDCache(); Но, судя по тому, что все перестает работать, включить не забыли.
Сообщение отредактировал Genadi Zawidowski - Feb 12 2017, 14:49
|
|
|
|
|
Feb 13 2017, 08:27
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 6-01-09
Пользователь №: 42 957

|
Genadi Zawidowski, спасибо за инфу; а можно уточнение? __DSB() вообще не поможет, или отдельно взятая? В Cortex M4 Programming Manual пишут, что она уместна после записи в эти самые DCCIMVAC. Это правда?
|
|
|
|
|
Feb 13 2017, 11:54
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 6-01-09
Пользователь №: 42 957

|
SasaVitebsk, Если в рамках тематики обсуждения, то в фирменном проекте от ST было подозрительное отличие от Cube-generated проектов такое: Код ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __attribute__((at(0x20001000)));/* Ethernet Rx MA Descriptor */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __attribute__((at(0x20001100)));/* Ethernet Tx DMA Descriptor */ Видимо ST уже знакомы с проблемой и знают как её обойти, но начинающим пользователям CubeMX не говорят. Если же вам нужен именно проект веб-сервера, то оригинала у меня нет и повторно найти его в сети не удалось. Поэтому могу выложить только тот проект, в котором я уже поковырялся. Это на случай, если Вам не приятно ковыряться в чужих черновиках. Кроме того, у меня сейчас нет платы 746-Discovery, поэтому проверить не могу, а отдаю как есть. Но в последний раз всё было настроено и начинало ра6отать сходу. Проект создан под Keil (к примеру, под IAR он так и не заработал). Вы можете скачать его здесь (270 мегабайт): yadi.sk/d/YBe4MA1k3E254v Распакуете целиком, потом смотрите путь в архиве: Projects\STM32746G-Discovery\Applications\LwIP\LwIP_HTTP_Server_Netconn_RTOS\MDK-ARM\Project.uvprojx Выберите таргет "Flash" и перекомпилируете программу, потому что по умолчанию у меня настроена отладка в оперативной памяти. Хотя в ней тоже всё работает: программа загружается кнопкой (d), как в начале обычного сеанса отладки, и крутится до первого сброса.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|