Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: lwIP: уведомление об изменении статуса линка
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Ноль с переносом
Здравствуйте! Курю примеры реализаций 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);
  }
Сергей Борщ
Я делаю netif_set_link_up(&NetIF)/netif_set_link_down(&NetIF). Но не в прерывании, а в потоке. Кроме того, в настройках есть #define LWIP_DHCP_CHECK_LINK_UP, поставьте его в нужное состояние. Использую версию 2.0.2, что было в более ранних - не знаю.
kolobok0
Цитата(Ноль с переносом @ Feb 7 2017, 14:44) *
... Допустим, прерывание об изменении физики получено;...


в этом кстати так-же необходимо убедиться. очень много разводок без заведения обратной связи от внешней физики.

примеры есть в стэке lwip. если коротко суть = необходимо подготовить как мк,
так и внешнюю микросхему (как правило, причина выставления активного уровня в физике - может быть разным и её надо так-же запрограммировать).
viakon
Цитата(Сергей Борщ @ 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мбит (пользователь выдернул шнурок из одного хаба и воткнул в другой)? Я эту проблему решил пока перезагрузкой.
Сергей Борщ
QUOTE (viakon @ Feb 8 2017, 06:46) *
Как обрабатываете, если сетка 100мбит сменилать на 10мбит (пользователь выдернул шнурок из одного хаба и воткнул в другой)? Я эту проблему решил пока перезагрузкой.
Вычитываю информацию из физики и пихаю в ETH->MACCR. Проверить не было возможности - у меня нет 10-Мбитных сосков вокруг. Но в описании запрета на запись в ETH->MACCR во время работы не нашел, значит можно.
viakon
Цитата(Сергей Борщ @ Feb 8 2017, 11:41) *
Вычитываю информацию из физики и пихаю в ETH->MACCR. Проверить не было возможности - у меня нет 10-Мбитных сосков вокруг. Но в описании запрета на запись в ETH->MACCR во время работы не нашел, значит можно.

netif_set_link_down
ETH->MACCR
netif_set_link_up

Так?
Сергей Борщ
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().
Ноль с переносом
Здравствуйте. Проблема временно решена следующим образом. Заведён выход прерывания, и 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, &regvalue); // Clears PHY intterrupt output
HAL_ETH_ReadPHYRegister(&heth, PHY_SR, &regvalue); // 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 часто и беспричинно подыхает. У меня, например, начал подыхать как только дело дошло до тестов на производительность. Вопрос: все эти стеки вообще отлажены? Или единственный выход - писать свои? В частности, мой механизм подыхания изображён на картинке.

Ноль с переносом
Здравствуйте ещё раз. Был опыт применения 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отать, как только дело доходит до этих тестов. Вопрос: есть ли другие, надёжные стеки? Или коммерческие организации в основном пишут свои?

Genadi Zawidowski
Как минимум, в нужных местах кода необходимо вызывать функции управление кэш-памятью:
Код
// Сейчас в эту память будем читать по 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, спасибо за инфу; а можно уточнение? __DSB() вообще не поможет, или отдельно взятая? В Cortex M4 Programming Manual пишут, что она уместна после записи в эти самые DCCIMVAC. Это правда?
SasaVitebsk
Ноль с переносом, а можно куда-нибудь положить примеры от st для 746 discovery?
Был бы очень благодарен.
Ноль с переносом
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), как в начале обычного сеанса отладки, и крутится до первого сброса.
Genadi Zawidowski
Цитата
__DSB() вообще не поможет, или отдельно взятая? В Cortex M4 Programming Manual пишут, что она уместна после записи в эти самые DCCIMVAC. Это правда?

Уместна... Но на работу с кэшем (который мы тут укрощаем) не влияет. Можете заглянуть в исходники упомянутых CMSIS функций.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.