J'essaie de faire apparaître un PCB qui utilise un STM32F407 et un LAN8720A Ethernet PHY, et je n'arrive pas à recevoir de trames Ethernet - même si je n'ai aucun problème à transmettre des trames.
Configuration materielle
J'ai un cristal de 25 MHz sur le STM32F4, entraînant une broche de sortie d'horloge de 25 MHz dans le LAN8720A, qui est en mode REF_CLK_OUT - et ramène une horloge de 50 MHz au STM32F4 dans le cadre de l'interface RMII.
Le jack / magnétique est une pièce générique. Voici la fiche technique:
Logiciel
J'utilise la dernière mise à jour STM32CubeMX pour générer un projet System Workbench pour STM32 qui contient FreeRTOS, lwIP, ainsi que les pilotes de périphériques ETH. Je n'ai pas vraiment touché au code généré - donc la pile lwIP est initialisée dans une pile FreeRTOS.
Expériences
Avec le lwIP de ma carte configuré pour une adresse IP statique 10.0.0.2 et un dongle USB vers Ethernet sur mon ordinateur configuré pour une adresse IP statique 10.0.0.1, je connecte les deux appareils directement avec un câble Ethernet et ma carte tente de se connecter à un service sur le port 80 de l'ordinateur. Je capture l'interaction entre ma carte et l'ordinateur à l'aide de Wireshark (fonctionnant sur l'ordinateur et lié au convertisseur USB-Ethernet).
En raison du problème de trames non reçues, nous ne dépassons jamais ce truc ARP: Comme vous pouvez le voir, le Stmicroe (ma carte) peut envoyer des paquets ARP - entendus par mon ordinateur - mais il ne semble jamais entendre la réponse de mon ordinateur , car il continue d'exploser les paquets ARP.
Les deux appareils sont configurés avec un masque 255.255.255.0 et les deux sont configurés avec une adresse de passerelle 10.0.0.1 (l'ordinateur). J'ai entendu parler de tables ARP vissées et d'ordinateurs ignorant les paquets ARP, mais je ne peux pas imaginer que la carte ignorerait les paquets ARP qui lui sont spécifiquement adressés par mon ordinateur - en réponse aux demandes que la carte a faites en premier lieu.
Donc, je plonge dans le fichier ethernetif.c de lwIP et je remarque qu'il HAL_ETH_GetReceivedFrame_IT(&heth)
retourne une erreur. Cette fonction renvoie une erreur car (heth->RxDesc->Status & ETH_DMARXDESC_OWN)
== 0, au lieu de 1. J'interprète cela comme signifiant que les tampons DMA sont actuellement armés pour le périphérique MAC et n'ont encore rien reçu.
De plus, j'ai vérifié que le HAL_ETH_IRQHandler n'est jamais appelé.
Un problème avec le PHY?
À ce stade, je soupçonnais que ma PHY était à blâmer.
Pour enquêter plus avant, j'ai attaché mon Saleae Logic Pro 16 à tous les signaux pertinents et j'ai remarqué qu'il y avait beaucoup de trafic sur les lignes TX0 / TX1, ainsi que RX0 / RX1. Voici une capture du trafic RX avec l'horloge d'entrée de 25 MHz:
RX_ERR est faible tout le temps, sauf si j'essaie de capturer la sortie d'horloge à 50 MHz (ce qui est évidemment difficile avec un appareil comme le Saleae): dans ce cas, RX_ERR est occulté à haute fréquence pour quelques paquets (ce qui est en fait un bon signe - la broche semble fonctionner).
Prochaines étapes
J'ai essayé d'activer manuellement les interruptions ETH en appelant HAL_NVIC_EnableIRQ(ETH_IRQn);
after tcpip_init()
is called dans la MX_LWIP_Init()
tâche, et cela ne semble pas résoudre le problème. Je ne suis pas tout à fait sûr que la routine d'interruption Ethernet soit même censée être appelée - c'est la chose difficile avec la mise en place d'un tout nouveau design; J'ai du mal à déterminer quel serait le bon comportement du système, je peux donc déterminer en quoi ma configuration diffère.
Bien que j'aie utilisé les trucs STM32 / STM32CubeMX / FreeRTOS auparavant, je n'ai jamais utilisé le périphérique Ethernet du STM32, et ma seule expérience avec ces trucs est sur des systèmes Linux embarqués personnalisés, qui semblaient toujours fonctionner simplement. C'est un nouveau territoire pour moi!
Je suis sûr qu'il y a une case stupide quelque part ou une Ethernet_EnableReceive()
fonction magique que j'oublie d'appeler, mais je ne trouve pas vraiment de documentation suggérant la nécessité d'activer explicitement ce genre de choses, et les messages que je vois sur Internet sont tous dus à des liens non liés problèmes.
Si quelqu'un a des idées, j'aimerais de l'aide!
Addendum: se débarrasser de FreeRTOS
Juste pour éliminer des choses, j'ai supprimé le composant du projet FreeRTOS, revenant à un projet bare-metal. Dans ma boucle principale, j'appelle MX_LWIP_Process()
. Cette méthode devrait éliminer le besoin d'interruptions, mais elle ne résout pas le problème; Je ne parviens toujours pas à recevoir de trames. Cela me fait penser qu'il y a quelque chose dans le code ETH HAL généré par STM32CubeMX.
Solution
Juste au cas où quelqu'un tomberait sur cette question à l'avenir, le problème s'est avéré être les broches RXD0 et RXD1 inversées. C'est pourquoi j'ai pu voir le trafic sur mon analyseur logique, mais il n'a pas été décodé par mon MCU.
Comme quelqu'un l'a souligné, les magnétiques que j'ai utilisés sont asymétriques et ne devraient pas être utilisés pour l'auto-MDI-X. Je n'ai eu aucun problème. Je prévois que deux choses se produisent: - les magnétiques ne fonctionnent pas réellement dans l'autre orientation, mais parce que tout ce que j'ai utilise auto-MDI-X, ma carte reste essentiellement fixe dans la configuration qui fonctionne, tandis que l'autre appareil allumé le câble oriente ses signaux pour qu'ils correspondent. - les magnétiques fournissent une intégrité de signal appropriée étant donné les courts trajets Ethernet, mais une analyse à long terme montrerait des taux plus élevés de perte de paquets ou de problèmes sur des trajets plus longs.
Honnêtement, je ne comprends pas pourquoi il importerait de quel côté du transformateur 1: 1 les filtres de ligne sont installés, donc en dehors des applications PoE, je ne sais pas pourquoi une conception symétrique vs asymétrique importerait.