реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> lwIP: уведомление об изменении статуса линка, стек не заводится, если изначально не подключен кабель
Ноль с переносом
сообщение Feb 7 2017, 11:44
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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] - для короткого!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 7 2017, 12:35
Сообщение #2


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Feb 7 2017, 21:16
Сообщение #3


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Ноль с переносом @ Feb 7 2017, 14:44) *
... Допустим, прерывание об изменении физики получено;...


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

примеры есть в стэке lwip. если коротко суть = необходимо подготовить как мк,
так и внешнюю микросхему (как правило, причина выставления активного уровня в физике - может быть разным и её надо так-же запрограммировать).
Go to the top of the page
 
+Quote Post
viakon
сообщение Feb 8 2017, 04:46
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 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мбит (пользователь выдернул шнурок из одного хаба и воткнул в другой)? Я эту проблему решил пока перезагрузкой.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 8 2017, 06:41
Сообщение #5


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
viakon
сообщение Feb 8 2017, 11:20
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 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

Так?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 8 2017, 11:38
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Ноль с переносом
сообщение Feb 10 2017, 06:17
Сообщение #8


Участник
*

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



Сообщение отредактировал IgorKossak - Feb 10 2017, 09:47
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!!
Go to the top of the page
 
+Quote Post
Ноль с переносом
сообщение Feb 12 2017, 11:37
Сообщение #9


Участник
*

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

Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 12 2017, 14:47
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
Ноль с переносом
сообщение Feb 13 2017, 08:27
Сообщение #11


Участник
*

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



Genadi Zawidowski, спасибо за инфу; а можно уточнение? __DSB() вообще не поможет, или отдельно взятая? В Cortex M4 Programming Manual пишут, что она уместна после записи в эти самые DCCIMVAC. Это правда?
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 13 2017, 09:27
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Ноль с переносом, а можно куда-нибудь положить примеры от st для 746 discovery?
Был бы очень благодарен.
Go to the top of the page
 
+Quote Post
Ноль с переносом
сообщение Feb 13 2017, 11:54
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 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), как в начале обычного сеанса отладки, и крутится до первого сброса.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 13 2017, 12:53
Сообщение #14


Профессионал
*****

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



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

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

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th August 2025 - 22:24
Рейтинг@Mail.ru


Страница сгенерированна за 0.01437 секунд с 7
ELECTRONIX ©2004-2016