Electronic – How to configure PHY in cubeMX on own board

ethernetlwipphystm32f2

I made a customboard using STM32f217VET microcontroller and KSZ8081 PHY (builtin pull-up resistors for TXP TXM and RXP RXM). I Configured my board to use MII mode, anda I used a 25MHz oscillator to do so. Here's my original schematic:

enter image description here

PS: I have already added the pull up 1k resistor for INTRP pin (32).

As of this moment I have tried 3 approaches to make this work (it is connected to a point that supports DHCP and is always assigned the same IP).

I initially tried to configure freeRTOS + lwIP with a custom PHY, since DP83843 was the only one on the list in cubeMX. With this I was never even able to get a link is up when reading the registers and auto-negotiation never completed. Not to mention that I was unable to receive any data from pins RXD0..RXD3 , even though I can see the differential input data in the RJ45 pins when I ping my board and I can see a 25MHz clock in RX_CLK pin. I just don't get any data. (I didn't try to see if it was sending data, yet)

Then tried using freeRTOS + lwIP using the default and only PHY available in cubeMX (DP83843). This apparently gave me a better result, it at least detects that the link is up, but still DHCP doesn't get any IP, but strangely I can see the same data in RX_Buff and TX_Buff (default DMA buffers created by cubeMX). Apparently It is seing the data and receiving it automatically? I doubt it, since it is not configured to be in loopback mode. I even followed some russian guide in youtube, which basically stated that I can ping my device without doing any modifictions to the source or at least I didn't see him do any modifications.

Afterwards I tried the most used method in tutorials online. lwIP baremetal. After the generated code I had to insert MX_LWIP_Process in the main loop, but still nothing.

OBS: I tried both enabling DHCP and forcing static IP.

The difference between tries 1 and 2 is the following modified code:

/* USER CODE END PHY_PRE_CONFIG */
#if 0 // Remove code to configure interrupt and change according to datasheet

  /**** Configure PHY to generate an interrupt when Eth Link state changes ****/
  /* Read Register Configuration */
  HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, &regvalue);

  regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);

  /* Enable Interrupts */
  HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue );

  /* Read Register Configuration */
  HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, &regvalue);

  regvalue |= PHY_MISR_LINK_INT_EN;
#endif    

  HAL_ETH_ReadPHYRegister(&heth, PHY_BCR, &regvalue);

   /* Read Register Configuration */
  HAL_ETH_ReadPHYRegister(&heth, 0x1BU, &regvalue);

  regvalue |= 0xFF00U; // Enable all interrupts

  /* Enable Interrupts */
  HAL_ETH_WritePHYRegister(&heth, 0x1BU, regvalue );

  /* Read Register Configuration */
  HAL_ETH_ReadPHYRegister(&heth, 0x1FU, &regvalue);

  regvalue |= (1U << 13U);
  /* Configure interrupt so that whenever an interrupt occurs a high level occurs. */

The code inside the "#if 0" is the coded provided by cubeMX and the rest is my code that I added to configure my PHY in my first try. This can be found in ethernetif.c near line 333

I have added projects 2 and 3 as attached files so everyone can see what I was doing, even if it was wrong. Attempt 1 differs from 2 just by the code snippet I added above.

I know that using my own board makes it harder to debug and for you to help me, but I have searched for projects that use MII instead of RMII and my connections are identical, even though the uC differs (from STM32f217 to STM32f439). Also I have an Olimex E407 board fi you have any suggestions for me to try (I know someone that has made freeRTOS and lwIP to work in the Olimex board, but I am unable to contactg this person at the moment)

In the lwipfreertos demo I added to the board it is possible to see that I send DHCP and in the Rx_Buff I can see the exact same message being received. This tells me that there is something being sent by the switch … maybe it even broadcasted my own message back to myself, but I don't really know if that's true. I know that when it is connected to the ethernet cable … the LEDs on the phy do not blink, they are completely off, but when I disconnect the cable I see the green LED blinking only to stop when I reconnect the cable

I just need to get this board to ping right now. If it pings I know that it is getting an IP and the stack is working … after that I can do anything else, but I can't even ping it at the moment .. much less get an IP

If necessary I can post the register values from the PHY or even probe something on my board

EDIT:

Just saw something i the datasheet that the guy that made the hardware didn't see. He used a J0026D RJ45 jack, which has integrated magnetics. Seeing KSZ8081's datasheet for the 20th time I noticed that since the differential TX and RX lines are alread terminated inside the PHY, the center tap pins should be connected to ground with individual 0.1u. In the board the center tap pins are connected to 3v3. I'll try to cut the connections to 3v3 and insert the caps.

EDIT2:

Found one problem with the center tap pins. They were connected to 3v3 and the design checklist indicates that the center tap pins must be connected to ground via 0.1uF capacitors .. so I removed the J0026D1NBL (magnetics in the connector) RJ45 jack, cut the 3v3 traces going to those pins, resoldered the jack and then connected a 100nF capacitor between pins 3 and 5 and 6 and 5 (3 and 6 are center tap pins and pin 5 is ground), each with their own capacitor as stated in the design checklist. This lead me to a different result .. if I power the board with the ethernet cable connected, it blinks the green light (LED0) and the yellow light is off … according to the datasheet the blinking light (in 00 mode) indicates activity and the LED1 pin off means it is in 100Mb/s mode. But If the cable is not connected, then the lights are off. These states do not change by connecting or disconnecting the cable during use, thy only change at the beginning of power up.

I've found some things that should be different but I think should not be a problem for what I'm doing. Apparently I'm missing the 33ohm (suggested 33 … may be different according to the application, but 33 is a good place to start) resistors in the RX and clock lines. Still … the PHY should be working properly and should be detecting communication and letting me receive data.

EDIT3:

GOT IT WORKING!!

Ok. My problem was specifically my soldering technique for my wireups. My poor vision led me to believe that the pins were properly connected when some were not, so I redid all the wireups, verified and reverified them a few times and I found that the INTRP wire up was on the wrong pin, on TX_CLK(still no problem because the other side wasn't properly soldered).

I actually got it working before @ajb's answer, and I had already done everything he posted (except verifyng the hardware connections properly). I still gave him the answer because he's absolutely right and it is a very good read and something everybody should take into consideration when designing well this type of boards, but it extends to absolutely every type of design … check everything possible, from hardware connections, registers, etc to software states and configurations.

Best Answer

There are many things that need to be working before you will be able to successfully ping your device.

  1. Your hardware needs to be connected properly
  2. Your PHY needs to be configured correctly
  3. The MCU's MAC needs to be configured correctly
  4. The LWIP stack needs to have the correct device drivers loaded and correct configuration applied.

We should be able to assume that CubeMX handles 3 and 4, but in practice, CubeMX has been known to generate buggy code. It's worth verifying that the CubeMX code is functioning correctly, but the high degree of abstraction makes that a time consuming activity, so we'll set that aside for now.

You've been going over the datasheet, which is good. You should also take a close look at the pin-strapping options for the PHY and make sure that everything is in order there. The odd behavior of the LEDs that you've described suggests there may be an issue here.

Next I would advise examining how the MCU configures the PHY. The SMI (MDIO/MDC) is fairly simple, so you should be able to create a simple test program that writes in whatever configuration data you want and/or reads out configuration and status data. Most PHYs, including the KSZ8081, will immediately negotiate a link with no configuration from the host as long as the pins are strapped correctly. You can verify this through the SMI.

If the SMI shows a properly negotiated link, then the hardware should be working. The next step should be to invoke the CubeMX-generated LWIP functionality, but if this is not successful you may want to do a lower level test involving sending test data manually. The Ethernet MAC and associated DMA controller are complicated, but while it will take some time to read and understand the datasheet, in the end it's not too complicated to transmit data from a single fixed buffer.

A packet-sniffing tool like Wireshark is invaluable here, and will continue to be useful even once you get your LWIP stack up and running. (Note that some devices/drivers will discard packets with invalid frame check sequences or other errors, so it's best to send a valid test packet--possibly one that you've captured off of a working link yourself. You may want to disable checksum validation in the device driver for your development computer's network interface if you can, so that Wireshark will show you bad packets.)

Once you're able to send a test packet successfully, you can revisit the CubeMX/LWIP code. Going through the datasheet will give you a better idea of how to interpret the MAC status registers and figure out where things are going wrong.