Estoy tratando de levantar un PCB que utiliza un STM32F407 y LAN8720A Ethernet PHY, y parece que no puedo recibir ninguna trama de Ethernet - a pesar de que no tengo ningún problema de transmisión de tramas.
Configuración del hardware
Tengo un cristal de 25 MHz en el STM32F4, que conduce un pin de salida de reloj de 25 MHz al LAN8720A, que está en modo REF_CLK_OUT - y conduce un reloj de 50 MHz de vuelta al STM32F4 como parte de la interfaz RMII.
El gato/magnético es una pieza genérica. Aquí está la hoja de datos:
Software
Estoy usando la última actualización de STM32CubeMX para generar un proyecto de System Workbench para STM32 que contiene FreeRTOS, lwIP, más los drivers de los periféricos ETH. Realmente no he tocado nada del código generado - así que la pila de lwIP se inicializa dentro de una pila de FreeRTOS.
Experimentos
Con el lwIP de mi placa configurado para una IP estática 10.0.0.2, y un dongle USB-a-ethernet en mi ordenador configurado para una IP estática 10.0.0.1, conecto los dos dispositivos directamente con un cable Ethernet, y mi placa intenta conectarse a un servicio en el puerto 80 del ordenador. Capturo la interacción entre mi placa y el ordenador utilizando Wireshark (que se ejecuta en el ordenador, y está vinculado al convertidor de USB a Ethernet).
Debido al problema de los fotogramas no recibidos, nunca pasamos de este asunto del ARP: Como puedes ver, el Stmicroe (mi placa) puede enviar paquetes ARP - escuchados por mi ordenador - pero nunca parece escuchar la respuesta de mi ordenador, ya que sigue enviando paquetes ARP.
Ambos dispositivos están configurados con una máscara 255.255.255.0, y ambos están configurados con una dirección de puerta de enlace de 10.0.0.1 (el ordenador). He oído que las tablas ARP se estropean y que los ordenadores ignoran los paquetes ARP, pero no puedo imaginar que la placa ignore los paquetes ARP dirigidos específicamente a ella por mi ordenador - en respuesta a las peticiones que la placa hizo en primer lugar.
Entonces, me sumerjo en el archivo ethernetif.c de lwIP y noto que HAL_ETH_GetReceivedFrame_IT(&heth)
devuelve un error. Esa función devuelve un error porque (heth->RxDesc->Status & ETH_DMARXDESC_OWN)
== 0, en lugar de 1. Interpreto que eso significa que los buffers DMA están actualmente armados para el periférico MAC, y no han recibido nada todavía.
Además, he comprobado que el HAL_ETH_IRQHandler nunca es llamado.
¿Un problema con el PHY?
En este punto, sospeché que el culpable era mi propio PHY.
Para investigar más a fondo, conecté mi Saleae Logic Pro 16 a todas las señales relevantes, y noté que hay mucho tráfico tanto en las líneas TX0/TX1, como en las RX0/RX1. Aquí hay una captura de algo de tráfico RX con el reloj de entrada de 25 MHz:
RX_ERR está bajo todo el tiempo, a menos que intente capturar la salida del reloj de 50 MHz (lo que obviamente es un reto con un dispositivo como el Saleae): en ese caso, RX_ERR se eleva ocasionalmente durante unos pocos paquetes (lo que en realidad es una buena señal - el pin parece estar funcionando).
Próximos pasos
He intentado habilitar manualmente las interrupciones ETH llamando a HAL_NVIC_EnableIRQ(ETH_IRQn);
después de tcpip_init()
se llama en el MX_LWIP_Init()
tarea, y eso no parece solucionar el problema. No estoy del todo seguro de que la rutina de interrupción de Ethernet sea siquiera se supone que se llama - eso es lo difícil de subir un diseño nuevo; estoy luchando por determinar cuál sería el comportamiento adecuado del sistema, para luego poder determinar cómo difiere mi configuración.
Aunque ya he utilizado el material de STM32/STM32CubeMX/FreeRTOS, nunca he utilizado el periférico Ethernet de STM32, y mi única experiencia con este material es en sistemas Linux embebidos personalizados, que siempre parecían funcionar sin más. Este es un nuevo territorio para mí.
Estoy seguro de que hay una estúpida casilla de verificación en algún lugar o mágica Ethernet_EnableReceive()
pero no puedo encontrar ninguna documentación que sugiera la necesidad de habilitar explícitamente esas cosas, y los mensajes que estoy viendo en Internet son todos debidos a problemas no relacionados.
Si alguien tiene alguna idea, ¡me encantaría recibir ayuda!
Apéndice: Deshacerse de FreeRTOS
Sólo para eliminar cosas, he eliminado el componente del proyecto FreeRTOS, volviendo a un proyecto bare-metal. En mi bucle principal, llamo a MX_LWIP_Process()
. Este método debería eliminar la necesidad de interrupciones, pero no soluciona el problema; sigo sin poder recibir tramas. Esto me hace pensar que hay algo en el código ETH HAL generado por STM32CubeMX.
Solución
Por si acaso alguien se tropieza con esta pregunta en el futuro, el problema resultó ser que los pines RXD0 y RXD1 estaban invertidos. Por eso pude ver el tráfico en mi analizador lógico, pero no fue decodificado por mi MCU.
Como alguien ha señalado, los imanes que utilicé son asimétricos, y no deberían utilizarse para auto-MDI-X. No he tenido ningún problema. Preveo que una de dos cosas está pasando - los magneticos no funcionan realmente en la otra orientacion, pero como todo lo que tengo usa auto-MDI-X, mi placa esencialmente se mantiene fija en la configuracion que funciona, mientras que el otro dispositivo en el cable orienta sus senales para que coincidan. - Los imanes proporcionan una integridad de la señal adecuada en los tramos cortos de Ethernet, pero un análisis a largo plazo mostraría mayores tasas de caída de paquetes o problemas en tramos más largos.
Sinceramente, no me queda claro por qué importaría en qué lado del transformador 1:1 se instalan los filtros de línea, así que fuera de las aplicaciones PoE, no estoy seguro de por qué importaría un diseño simétrico o asimétrico.