stm32-rs / stm32-eth

Embedded Ethernet driver in Rust
Apache License 2.0
147 stars 47 forks source link

Getting started guide #25

Open jiayihu opened 3 years ago

jiayihu commented 3 years ago

Hi, I'm new into embedded stuff and I have an STM32F4 Disc board. What do I need in order to use this crate? Do you have any starting guide?

I'm currently trying to understand the needed hardware. emcraft suggests to use a WaveShare DP83848, but #8 seems to imply that it's not supported by this crate. Japaric has a blog post about embedded ethernet using ENC28J60, what should I buy?

thalesfragoso commented 3 years ago

I have used a cheap LAN8720 module from aliexpress without problems. Mine was strapped to a PHY address of 1 btw.

jiayihu commented 3 years ago

So do you mean something like this? https://www.amazon.it/TECNOIOT-Ethernet-Transceiver-Interface-Development/dp/B07VN9Q4QK/ (I know it's in Italian, but I hope you can confirm it by having a look at the picture) And how can I connect it to the board? I also already bought some pin-to-pin wire, I guess I have to use them but I don't know the mapping

thalesfragoso commented 3 years ago

Yeah, that one is similar to the one I have. I used jumper wires to connect them, not really recommend for proper designs, but it worked.

Here you can see the pin mapping that we use: https://github.com/stm32-rs/stm32-eth/blob/4d6b29bf1ecdd1f68e5bc304a3d4f170049896c8/src/setup.rs#L194-L225

jiayihu commented 3 years ago

I have connected the pins of the LAN8720 module as specified and modified the ip example with my mapping as follows:

let eth_pins = EthPins {
        ref_clk: gpioa.pa1,
        md_io: gpioa.pa2,
        md_clk: gpioc.pc1,
        crs: gpioa.pa7,
        tx_en: gpiob.pb11,
        tx_d0: gpiob.pb12,
        tx_d1: gpiob.pb13,
        rx_d0: gpioc.pc4,
        rx_d1: gpioc.pc5,
};

But when I try to run the code it hangs at the following line:

https://github.com/stm32-rs/stm32-eth/blob/4d6b29bf1ecdd1f68e5bc304a3d4f170049896c8/src/lib.rs#L238

Any idea about what should I do? I found online that I should check the clock output frequency from PA1 pin but I don't have a oscillograph. Also, is it maybe relevant that some guides say that I should modify the board by removing the gyro? For instance, it's pointed here and here. This seems to be a specific issue of the STM32F429 Discovery board, what stm32 model have you used?

jiayihu commented 3 years ago

Okay solved: for future reference it means cutting the pins n° 6 and 7 in the U3 unit which are connected to two small holes, which on the back of the board are connected to the pin PA1. Pins are numbered anti-clockwise from the one with a white dot. You literally have to cut the pins using a small cutter.

jiayihu commented 3 years ago

New update for future reference: after cutting the traces and removing the resistors as described here, I was able to see some logs I wasn't being able to transmit.

The board would also block on this software reset:

https://github.com/stm32-rs/stm32-eth/blob/4d6b29bf1ecdd1f68e5bc304a3d4f170049896c8/src/lib.rs#L148

After some tests I noticed that attaching and removing the VCC jumper from the pin allowed the board to continue and pktgen started to report a detected link with 0Mbps and unknown duplex status. Then I remembered that @thalesfragoso you said yours was strapped to PHY address of 1. I couldn't find a clear explanation of what a PHY address is and what "strapping" means but changing to PhyAddress::_1 solved the issue indeed. Now I can always see the log Ethernet: link detected with 100 Mbps/FD.

So could anyone explain what is a PHY address and strapping means? I'm planning then to write a detailed tutorial for anyone who is beginning with embedded in Rust from my own experience.

adamgreig commented 3 years ago

PHY address

As well as exchanging ethernet data with the PHY using the RMII interface (REFCLK, TXD, TXEN, RXD, CRS_DV), the STM32 also communicates with the PHY using a two-wire interface a bit like I2C, called MDIO (with MDC and MDIO pins). It's used for configuration and status of the PHY, and it's a bus that can have multiple PHYs on it (for example a switch might have one per port and talk to all of them over one MDIO bus).

Just like I2C, the PHYs have a 5-bit address and the STM32 starts each transfer on the MDIO bus by addressing a specific PHY. The addresses are sometimes hardcoded at the factory (often to 0 or 1), or sometimes can be set by the user, again a lot like I2C. Sometimes they always start at address 0, but can be programmed to another address using MDIO.

Strapping

Strapping refers to putting pullup or pulldown resistors on certain pins of the PHY which normally have another function, where the pullup/pulldown is just read at reset to set a configuration bit. For example, the TXD0 pin might normally be part of the RMII interface sending high-speed ethernet data, but on particular PHY you might be able to add a pullup or pulldown resistor to configure some property, such as a bit of the MDIO address, or whether an LED should blink when there's traffic, that sort of thing. Usually these configuration bits can be set over MDIO as well, but it can be more convenient to set them in hardware and then not need MDIO (or allow a simpler firmware).

Hope that helps explain it but please ask if anything's still not clear!