Turgenev 1 20 июня Опубликовано 20 июня (изменено) · Жалоба Работаю с RAW LwIP на плате NUCLEO-H743ZI2 и случайно обратил внимание, что 99.9% времени, затрачиваемого на запуск контроллера (выход на цикл while(1)) приходится на функцию инициализации MX_LWIP_Init(). На 400 МГц тактовой частоты ядра это время составляет 2 секунды. Измерял вот так: Спойлер cnt_ms_load_mcu = HAL_GetTick(); MX_LWIP_Init(); cnt_ms_load_mcu = HAL_GetTick() - cnt_ms_load_mcu; Архив с проектом прилагаю: Спойлер Nikiten_STM32_Eth.zip Хотел узнать, у вас так же? Кто-нибудь ускорял инициализацию этой библиотеки? Изменено 20 июня пользователем Turgenev Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 153 20 июня Опубликовано 20 июня · Жалоба Думается мне, что Вы измеряете скорость автосогласования Ethernet PHY... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 206 21 июня Опубликовано 21 июня · Жалоба 12 часов назад, Arlleex сказал: Думается мне, что Вы измеряете скорость автосогласования Ethernet PHY... Я ТС-у об этом писал в другой теме. Только думаю, что он всё равно ничего не понял. Так как не знает и не желает знать - что делает какая часть его же кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Turgenev 1 Пятница в 19:41 Опубликовано Пятница в 19:41 · Жалоба Ваши сомнения в такой долгой инициализации натолкнули на поиски. Причина оказалась проста. Код из lan8742.c: Спойлер /* Wait for 2s to perform initialization */ while((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO) { } Комментарий от разработчиков ST в теме (осторожно, очень жесткая критика): Спойлер https://community.st.com/t5/stm32-mcus-embedded-software/stm32h7-phy-driver-for-lan8742-2s-delay/td-p/112767/page/2 Удаление этой 2 сек задержки, предварительно, на работу сети Ethernet не повлияло- пингую, отправляю, принимаю пакеты на 100 МБ/с. Из темы на форуме ST и из кода так и не понял зачем ждать 2 секунды, если PHY и MAC и без нее синхронизируются. 14 часов назад, jcxz сказал: Я ТС-у об этом писал в другой теме. Только думаю, что он всё равно ничего не понял. Так как не знает и не желает знать - что делает какая часть его же кода. Что делает написанный мной код я желаю знать и знаю. Что делает код сторонних библиотек мне достаточно знать в самом общем смысле, если работа библиотеки удовлетворяет моим требованиям, иначе зачем я ее использую. Безусловно полезно знать все на свете, но возможностей для этого не достаёт. Неужели это не так работает? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 153 Пятница в 20:18 Опубликовано Пятница в 20:18 · Жалоба Ды можно и не вдаваться в подробности работы сторонних исходников, но ведь Вам пришлось же вдаваться, как минимум) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Turgenev 1 Пятница в 21:05 Опубликовано Пятница в 21:05 · Жалоба Ну вы сказали что не должно быть так, я и полез... Мои коллеги несколько лет на это не обращали внимание Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 206 Суббота в 03:12 Опубликовано Суббота в 03:12 · Жалоба 7 часов назад, Turgenev сказал: Удаление этой 2 сек задержки, предварительно, на работу сети Ethernet не повлияло- пингую, отправляю, принимаю пакеты на 100 МБ/с. Из темы на форуме ST и из кода так и не понял зачем ждать 2 секунды, если PHY и MAC и без нее синхронизируются. Вам уже и написали выше про наиболее вероятную причину - зачем нужна эта задержка: В 20.06.2024 в 18:58, Arlleex сказал: автосогласования Ethernet PHY но вы ведь всё равно не поняли. Предпочитаете пинать колёса, а не вникать. 7 часов назад, Turgenev сказал: Что делает написанный мной код я желаю знать и знаю. Что делает код сторонних библиотек Как только какой-то код, не важно где откопанный, вы влепили в свой проект, он стал вашим кодом. 7 часов назад, Turgenev сказал: Неужели это не так работает? Когда ваше устройство вдруг перестаёт работать, вы тоже заказчику говорите: "Это проблема не у меня, а в той либе, которую я влепил в свой проект. А я не при делах." Так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Turgenev 1 Понедельник в 09:34 Опубликовано Понедельник в 09:34 · Жалоба Распишу почему мне не понятно, зачем нужна задержка. Задержка в 2 секунды находится в функции LAN8742_Init(lan8742_Object_t *pObj), в которой не происходит автосогласования, а только конфиг PHY, поправьте если не прав. Процесс автосогласования запускается автоматически после сброса PHY: Спойлер /** * @brief Initialize the lan8742 and configure the needed hardware resources * @param pObj: device object LAN8742_Object_t. * @retval LAN8742_STATUS_OK if OK * LAN8742_STATUS_ADDRESS_ERROR if cannot find device address * LAN8742_STATUS_READ_ERROR if connot read register * LAN8742_STATUS_WRITE_ERROR if connot write to register * LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset */ int32_t LAN8742_Init(lan8742_Object_t *pObj) { uint32_t tickstart = 0, regvalue = 0, addr = 0; int32_t status = LAN8742_STATUS_OK; if(pObj->Is_Initialized == 0) { if(pObj->IO.Init != 0) { /* GPIO and Clocks initialization */ pObj->IO.Init(); } /* for later check */ pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1; /* Get the device address from special mode register */ for(addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++) { if(pObj->IO.ReadReg(addr, LAN8742_SMR, ®value) < 0) { status = LAN8742_STATUS_READ_ERROR; /* Can't read from this device address continue with next address */ continue; } if((regvalue & LAN8742_SMR_PHY_ADDR) == addr) { pObj->DevAddr = addr; status = LAN8742_STATUS_OK; break; } } if(pObj->DevAddr > LAN8742_MAX_DEV_ADDR) { status = LAN8742_STATUS_ADDRESS_ERROR; } /* if device address is matched */ if(status == LAN8742_STATUS_OK) { /* set a software reset */ if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0) { /* get software reset status */ if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) >= 0) { tickstart = pObj->IO.GetTick(); /* wait until software reset is done or timeout occured */ while(regvalue & LAN8742_BCR_SOFT_RESET) { if((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO) { if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) < 0) { status = LAN8742_STATUS_READ_ERROR; break; } } else { status = LAN8742_STATUS_RESET_TIMEOUT; break; } } } else { status = LAN8742_STATUS_READ_ERROR; } } else { status = LAN8742_STATUS_WRITE_ERROR; } } } if(status == LAN8742_STATUS_OK) { tickstart = pObj->IO.GetTick(); /* Wait for 2s to perform initialization */ /* while((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO) { }*/ pObj->Is_Initialized = 1; } return status; } Т.е. ожидание 2 с оправдано тем, что происходит процесс автосогласования, который автоматически начался после сброса PHY. Но в RAW LwIP обработка пакетов происходит вызовом функции MX_LWIP_Process() в бесконечном цикле, в которой есть функция работы с PHY - Ethernet_Link_Periodic_Handle(struct netif *netif). Эта функция проверяет состояние канала и возможность/необходимость перехода на другую скорость функцией ethernet_link_check_state(struct netif *netif): Спойлер /** * @brief Check the ETH link state then update ETH driver and netif link accordingly. * @param argument: netif * @retval None */ void ethernet_link_check_state(struct netif *netif) { ETH_MACConfigTypeDef MACConf; int32_t PHYLinkState; uint32_t linkchanged = 0, speed = 0, duplex =0; PHYLinkState = LAN8742_GetLinkState(&LAN8742); if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) { HAL_ETH_Stop(&heth); netif_set_down(netif); netif_set_link_down(netif); } else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) { switch (PHYLinkState) { case LAN8742_STATUS_100MBITS_FULLDUPLEX: duplex = ETH_FULLDUPLEX_MODE; speed = ETH_SPEED_100M; linkchanged = 1; break; case LAN8742_STATUS_100MBITS_HALFDUPLEX: duplex = ETH_HALFDUPLEX_MODE; speed = ETH_SPEED_100M; linkchanged = 1; break; case LAN8742_STATUS_10MBITS_FULLDUPLEX: duplex = ETH_FULLDUPLEX_MODE; speed = ETH_SPEED_10M; linkchanged = 1; break; case LAN8742_STATUS_10MBITS_HALFDUPLEX: duplex = ETH_HALFDUPLEX_MODE; speed = ETH_SPEED_10M; linkchanged = 1; break; default: break; } if(linkchanged) { /* Get MAC Config MAC */ HAL_ETH_GetMACConfig(&heth, &MACConf); MACConf.DuplexMode = duplex; MACConf.Speed = speed; HAL_ETH_SetMACConfig(&heth, &MACConf); HAL_ETH_Start(&heth); netif_set_up(netif); netif_set_link_up(netif); } } } А состояние/результат работы автосогласования проверяется/устанавливается в функции LAN8742_GetLinkState(lan8742_Object_t *pObj): Спойлер /** * @brief Get the link state of LAN8742 device. * @param pObj: Pointer to device object. * @param pLinkState: Pointer to link state * @retval LAN8742_STATUS_LINK_DOWN if link is down * LAN8742_STATUS_AUTONEGO_NOTDONE if Auto nego not completed * LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD * LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD * LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD * LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD * LAN8742_STATUS_READ_ERROR if connot read register * LAN8742_STATUS_WRITE_ERROR if connot write to register */ int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj) { uint32_t readval = 0; /* Read Status register */ if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0) { return LAN8742_STATUS_READ_ERROR; } /* Read Status register again */ if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0) { return LAN8742_STATUS_READ_ERROR; } if((readval & LAN8742_BSR_LINK_STATUS) == 0) { /* Return Link Down status */ return LAN8742_STATUS_LINK_DOWN; } /* Check Auto negotiaition */ if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) < 0) { return LAN8742_STATUS_READ_ERROR; } if((readval & LAN8742_BCR_AUTONEGO_EN) != LAN8742_BCR_AUTONEGO_EN) { if(((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) && ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)) { return LAN8742_STATUS_100MBITS_FULLDUPLEX; } else if ((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) { return LAN8742_STATUS_100MBITS_HALFDUPLEX; } else if ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE) { return LAN8742_STATUS_10MBITS_FULLDUPLEX; } else { return LAN8742_STATUS_10MBITS_HALFDUPLEX; } } else /* Auto Nego enabled */ { if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_PHYSCSR, &readval) < 0) { return LAN8742_STATUS_READ_ERROR; } /* Check if auto nego not done */ if((readval & LAN8742_PHYSCSR_AUTONEGO_DONE) == 0) { return LAN8742_STATUS_AUTONEGO_NOTDONE; } if((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_FD) { return LAN8742_STATUS_100MBITS_FULLDUPLEX; } else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_HD) { return LAN8742_STATUS_100MBITS_HALFDUPLEX; } else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_10BT_FD) { return LAN8742_STATUS_10MBITS_FULLDUPLEX; } else { return LAN8742_STATUS_10MBITS_HALFDUPLEX; } } } Тогда зачем ждать железные 2 с при старте, ни к чему не привязанные (может времени нужно больше или меньше), когда в процессе работы согласование PHY с MAC и так постоянно проверяется? Если задержка сделана на случай, если не удалось согласование при старте, оно по-любому запустится в процессе работы. По-моему, это уже не по теме: Спойлер В 22.06.2024 в 06:12, jcxz сказал: но вы ведь всё равно не поняли. Предпочитаете пинать колёса, а не вникать. Так можно отвечать на все вопросы, когда кому-то что-то не понятно. Нашел задержку и тему где она описана- пинал колеса, в этой теме не понял что-то - не хочешь вникать. Не прикрывайтесь советами других, действуйте более открыто, будет меньше текста. В 22.06.2024 в 06:12, jcxz сказал: Когда ваше устройство вдруг перестаёт работать, вы тоже заказчику говорите: "Это проблема не у меня, а в той либе, которую я влепил в свой проект. А я не при делах." Так? Не судите по себе, есть тестировщики, этапы разработки, испытания и тд. Кто заказчику не обкатанное изделие отдает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Turgenev 1 Вчера в 12:02 Опубликовано вчера в 12:02 (изменено) · Жалоба Получил проблему из-за удаления 2с задержки в инициализации PHY: соединение по Ethernet устанавливается только после второй перезагрузки устройства, после прошивки МК. Т.е. прошиваю МК, перезагружаю всё устройство и связи по ethernet нет, затем перезагружаю устройство второй раз и связь появляется. Проблема описана вот тут: Спойлер https://community.st.com/t5/stm32-mcus-embedded-software/stm32f207vc-ethernet-with-lwip-works-after-flashing-but-not-any/td-p/276626/page/2 Вкратце: PHY возвращает 0xFFFF при чтении любого его регистра. Малой кровью проблема решается добавлением проверки в LAN8742_Init перед первым чтением регистра PHY в этой функции: Спойлер pObj->IO.ReadReg(0, LAN8742_SMR, ®value); if (regvalue == 0x0000FFFF) { HAL_NVIC_SystemReset(); } Может кому-то будет полезно... Изменено вчера в 12:04 пользователем Turgenev Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться