Перейти к содержанию
    

lwIP: уведомление об изменении статуса линка

Здравствуйте! Курю примеры реализаций 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
[codebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я делаю netif_set_link_up(&NetIF)/netif_set_link_down(&NetIF). Но не в прерывании, а в потоке. Кроме того, в настройках есть #define LWIP_DHCP_CHECK_LINK_UP, поставьте его в нужное состояние. Использую версию 2.0.2, что было в более ранних - не знаю.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

... Допустим, прерывание об изменении физики получено;...

 

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

 

примеры есть в стэке lwip. если коротко суть = необходимо подготовить как мк,

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я делаю netif_set_link_up(&NetIF)/netif_set_link_down(&NetIF). Но не в прерывании, а в потоке. Кроме того, в настройках есть #define LWIP_DHCP_CHECK_LINK_UP, поставьте его в нужное состояние. Использую версию 2.0.2, что было в более ранних - не знаю.

Как обрабатываете, если сетка 100мбит сменилать на 10мбит (пользователь выдернул шнурок из одного хаба и воткнул в другой)? Я эту проблему решил пока перезагрузкой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как обрабатываете, если сетка 100мбит сменилать на 10мбит (пользователь выдернул шнурок из одного хаба и воткнул в другой)? Я эту проблему решил пока перезагрузкой.
Вычитываю информацию из физики и пихаю в ETH->MACCR. Проверить не было возможности - у меня нет 10-Мбитных сосков вокруг. Но в описании запрета на запись в ETH->MACCR во время работы не нашел, значит можно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вычитываю информацию из физики и пихаю в ETH->MACCR. Проверить не было возможности - у меня нет 10-Мбитных сосков вокруг. Но в описании запрета на запись в ETH->MACCR во время работы не нашел, значит можно.

netif_set_link_down

ETH->MACCR

netif_set_link_up

 

Так?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так?
Без первой строчки. Ибо если линк разорван, то что писать в ETH->MACCR? А если он уже установлен, то и меняться там нечему.

 

В обработчике прерывания физики по флагу Autonegotiation complete пишу MACCR, ставлю флаг "связь есть", разрешаю прерывание физики по флагу Link down. При получении прерывания Link down сбрасываю флаг "связь есть" и разрешаю прерывание Autonegotiation complete. В основном цикле при изменении флага "связь есть" делаю netif_set_link_up() или netif_set_link_down().

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте. Проблема временно решена следующим образом. Заведён выход прерывания, и DP83848 настроена на выдачу прерывания по изменению статуса линка. Но само прерывание не подключено, вместо этого в одном из потоков несколько раз в секунду вызывается следующая штука:

 

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

 

00000001.jpg

Изменено пользователем IgorKossak
[codebox] для длинного кода. [code]-для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как минимум, в нужных местах кода необходимо вызывать функции управление кэш-памятью:

// Сейчас в эту память будем читать по 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ноль с переносом, а можно куда-нибудь положить примеры от 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), как в начале обычного сеанса отладки, и крутится до первого сброса.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

__DSB() вообще не поможет, или отдельно взятая? В Cortex M4 Programming Manual пишут, что она уместна после записи в эти самые DCCIMVAC. Это правда?

Уместна... Но на работу с кэшем (который мы тут укрощаем) не влияет. Можете заглянуть в исходники упомянутых CMSIS функций.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...