Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for "real" Ethernet hardware #29

Open
kripton opened this issue Jan 7, 2022 · 18 comments
Open

Support for "real" Ethernet hardware #29

kripton opened this issue Jan 7, 2022 · 18 comments
Labels
enhancement New feature or request hardware Anything related to schematics or PCB layouts
Milestone

Comments

@kripton
Copy link
Member

kripton commented Jan 7, 2022

The current implementation emulates a network device via USB (CDC NCM) so that the host computer can transfer data via IP packets (web interface, ArtNet, E1.31/sACN). However, attaching a real Ethernet device could be beneficial. One could build a standalone 16-port ArtNet-to-DMX adapter.

However, the rp2040 only has a limited amount of GPIO pins and there are probably not enough to cater for a LAN8720 board (except if some of its pins were optional). There might be Ethernet-Boards that attach via I2C (no additional pins required) or SPI (one additional pin required for the CE line).

This will also require quite some refactoring on the software side. We could go all the way to allow packet forwarding from the emulated USB network interface to the "real" Ethernet hardware, so the dongle could be used as USB-to-Ethernet adapter as well. I assume that would not be worth the effort ;)

@kripton kripton added enhancement New feature or request hardware Anything related to schematics or PCB layouts labels Jan 7, 2022
@6by9
Copy link

6by9 commented Jun 15, 2022

I was looking at the same thing as I was wanting a simple ArtNet to DMX adapter with some internal control.

https://github.com/krystiancha/pico-enc28j60.git works quite nicely for the SPI ENC28J60 ethernet adapter on Pico. It wants an interrupt line as well as chip select.
The Pico SPI interface seems to leave the chip select line up to the app rather than being handled in hardware, so any GPIOs can be used for chip selects. SPI accesses can then be wrapped in a blocking interface that serialises accesses from multiple users (RF24 and ENC28J60). There may need to be some extra hardware logic to ensure that both RF24 and ENC28J60 tri-state their SDO line when deselected (they're meant to, but not all devices do).

The other question is whether you can run multiple interfaces through LWIP simultaneously - it looks like that is possible.
You also want the TinyUSB interface to run dhcpd, but not on the wired interface, so there are a few more little issues to solve.

@kripton
Copy link
Member Author

kripton commented Jun 16, 2022

Nice, that code example looks pretty useful. I thought the enc28j60 might take some more work and pins to get running but the effort looks manageable. The only pin on the Pico board that is still unused is GPIO 27, so I would plan that as CS line for the ENC chip. However, there is no GPIO left for interrupt, expect if we drop 26's function to trigger scopes at the beginning of a DMX frame. For the nRF24 interrupt there is really no pin left then and right now the code polls the chip if packets have been received. When the SPI bus is shared between the ENC and the nRF24, this might introduce delays. On the other hand, the SPI can run at 10 MHz (at least with the nRF24 only, I didn't check the ENC chip) so that should be fast enough. And even then it would only matter if folks use both Ethernet and wireless at the same time. Also I didn't see the code where the example you linked to defines or uses the interrupt PIN. Might have missed that though.
Yes, lwIP can handle multiple interfaces. The current code has a define set for single-interface mode to save code space, runtime memory and CPU usage but of course one can check if it works having two interfaces, the USB one with fixed IP and the Ethernet with IP from DHCP or fixed as well.
I might have some ENC breakout boards lying around, I will take a look this evening.

@kripton
Copy link
Member Author

kripton commented Jun 16, 2022

I just looked that up: The ENC28J60's SPI interface supports up to 20MHz, so staying with the current 10MHz should be fine

@kripton
Copy link
Member Author

kripton commented Jun 16, 2022

Okay, I also found the place where the interrupt Pin is being configured and used: https://github.com/krystiancha/pico-enc28j60/search?q=INT_PIN
Well, we will ise GPIO 26 for that then and now really all GPIOs are in use.
As an alternative, one could add an I2C-attached GPIO chip for the two CS pins and the CE pin of the nRF24. Might make the SPI communication a bit slower though

@6by9
Copy link

6by9 commented Jun 16, 2022

Also I didn't see the code where the example you linked to defines or uses the interrupt PIN. Might have missed that though.

https://github.com/krystiancha/pico-enc28j60/blob/master/src/examples/lwip_integration.c#L95

Sharing SPI will have locking issues as your RF24 code is running on core1 whilst enc28j60 is likely to be on core0.

I suspect that having either RF24 or wired ethernet will be more stable, but it's always fun to push the boundaries.

@kripton
Copy link
Member Author

kripton commented Jun 16, 2022

What someone suggested (https://electronics.stackexchange.com/questions/441991/use-pcf8574-switch-selection-multiple-spi-slave-devices-is-it-possible) is to have both devices on the same CS pin , the one with an inverter. That would make the CS pin toggle between the one or the other device. Sounds a bit crude to me but worth an investigation if it's faster and cheaper than using an IO expander

@kripton
Copy link
Member Author

kripton commented Jun 26, 2022

Okay, first progress report. Also more or less for myself so I can remember what I did, what worked and what didn't.
I found and hooked up an ENC28J60 via SPI to the Pico running the dmxsun software. With the pico-enc28j60 unchanged and the nRF24-module-code active (although no radio module attached), it didn't work. However, when I modified the enc28j60-code a little (to re-init the SPI before every read and write), the pico started to react to ping-messages 🥳 . This also worked fine with SPI@20MHz over breadboard-wire and with the logic analyzer attached.
The web server was also working as expected and the WebUI was usable over Ethernet. However, when I started sending ArtNet-frames via QLC+ (one universe only, for now), the WebUI stopped updating and the board stopped sending ping-replies. The interrupt-line between the enc28j60 and the Pico as well as the SPI traffic were still looking normally but with increased traffic, of course.. When I stopped sending ArtNet-frames, the SPI traffic went back to the previous patterns but the ping-replies were still missing. Needs investigation if it's a (hardware) issue in the enc28j60-board (or maybe an RX overflow) or something that can be fixed in software. I also read people complaining about the enc28j60 being unstable. Might also be that.

Also still on my TODO: Verify that Ethernet works with an nRF24-module also attached to the board. With and without wireless traffic. Additionally, all tests were done with the USB cable of the Pico disconnected (and powered externally), so I never had two net-interfaces UP at the same time in the lwIP-stack.

So, in general the integration of the enc28j60 works, pinout is fine, basic functionality working but quite some work remaining.

@kripton
Copy link
Member Author

kripton commented Jun 26, 2022

WiP branch: main...kripton:ethernet

@kripton
Copy link
Member Author

kripton commented Jun 27, 2022

Today's achievement: I can successfully receive and process ArtNet via the enc28j60-board. Right now, 4 universes are working fine. However, at some point the emulated network interface via USB stops working. With one or two universes both network interfaces are working. When more data is coming in via Ethernet, the USB network just stops. Might be due to load, might be due to locking issues. I'm honestly thinking to either introduce a proper task/thread management or re-base the whole work to be on top some free RTOS so both cores can be used most efficiently.

Also what doesn't yet work is initializing and using the enc28j60 when the nRF24 module is present. The latter always takes precedence and blocks the ethernet module. I didn't investigate deeper since connecting the nRF24, the enc28j60, a logic analyzer and probably the picoprobe debugger as well requires some more advances wiring here ;)

@6by9
Copy link

6by9 commented Jun 30, 2022

https://www.raspberrypi.com/news/raspberry-pi-pico-w-your-6-iot-platform/ would be the other reason I was looking at alternate network hardware with this project.
Sadly time hasn't allowed me to get it working as yet.

@kripton It should be available from the normal suppliers, but if you wanted a couple of samples then drop me an email with your address (dave.stevenson at the same domain as the blog post).

@kripton kripton added this to the v1.1.0 milestone Nov 6, 2022
@framethespace
Copy link

Hi, this might be a stupid question, but what are the advantages of an ENC28J60 over the W5500 which seems to be cheaper, more available and has good community support (Arduino and such), again, I might be mistaking :)

@6by9
Copy link

6by9 commented Nov 11, 2022

Hi, this might be a stupid question, but what are the advantages of an ENC28J60 over the W5500 which seems to be cheaper, more available and has good community support (Arduino and such), again, I might be mistaking :)

When I looked at it the W5500 appeared to be doing the TCP/IP side as well, rather than just the base ethernet.
That reduces flexibility if you want to do a non-IP based protocol, is likely to be trickier to integrate alongside lwip, and I wasn't sure whether you could get direct access to the sockets in a tidy manner.

Doing a search now does appear to list some Lwip integrations with W5500, referencing a "MAC RAW" mode, so I may have just missed it.

This is one of the useful parts of adopting Lwip - the actual networking layer is largely abstracted from the application, so if you can find a suitable library to talk to an ABC123 interface, then a lot of the complexity is removed.
There was initial work required to migrate away from TinyUSB as it required polling. Many other interfaces are interrupt driven.

@kripton
Copy link
Member Author

kripton commented Nov 15, 2022

Hi, this might be a stupid question, but what are the advantages of an ENC28J60 over the W5500 which seems to be cheaper, more available and has good community support (Arduino and such), again, I might be mistaking :)

There are no stupid questions :)
As @6by9 said, when the investigations were started, the ENC28J60 seemed to be the only reasonable solution that works fine with the lwIP-stack that was already in use for the CDC-ECM "Ethernet over USB" emulation. I read about the W5500 briefly and it was mainly advertised for its advanced stack that handles IP and UDP/TCP right inside the chip. While this might make sense, I was looking for something more universal. I was not aware about the "MacRaw" mode that allows it to work with lwIP just fine. Thanks for pointing it out.

I have now added an Ethernet-chip/module to the baseboard (#57) and the W5500 / WIZ850io module (some also call it USR-ES1) won for one reason: It has a form factor and footprint that can be easily added as a module to an existing board just via pin headers / sockets.
For the ENC28J60 I found only modules where the pin headers point upwards from the PCB or that are designed to work with 5V ("ENC28J60 nano shield"). It could be that they work with 3.3V just fine but I'd rather try the MacRaw mode of the WIZ850io instead.

The pricing is not much different. Depending on where you look, one or the other is cheaper. Cheapest WIZ850io I was able to find: https://www.ebay.com/itm/374331130878. And that's reeeeaally cheap (the IC itself costs about the same on JLCPCB). I just hope they ship from china with the W5500 chip displayed in the photos and not some incompatible rip-off. We will see when they arrive and I decide to order the next batch of baseboards from JLCPCB.

@kripton
Copy link
Member Author

kripton commented Nov 15, 2022

Oh, and I just found out that JOY-IT (one producer or designer of the USR-ES1 module) advertises the Pico compatibility in its manual: https://www.joy-it.net/files/files/Produkte/SBC-USR-ES1/SBC-USR-ES1_Manual_2021-04-22.pdf

@kripton
Copy link
Member Author

kripton commented Nov 27, 2022

One issue I thought the W5500 has against the ENC28J60: It doesn't ship with a MAC address, so one would need to officially obtain some. As those need to be worldwide-unique, one would have to buy/register some. However, I just found out that the ENC28J60 actually also doesn't ship/own a MAC address of its own. So the problem is just the same.
Current solution is a hard-coded MAC address in the code: main...kripton:ethernet#diff-b19fa52232c63d710013de1b71c312c53e5ab33893f4b47983682b5fa93b8486R8

Maybe we could just do as most Desktop Virtualization software does: Have a fixed vendor ID and randomly generate the remaining three bytes. Or use the last three bytes of the Pico's unique ID as the MAC address.

@kripton
Copy link
Member Author

kripton commented Nov 27, 2022

What would work and would be perfectly legal: https://github.com/openmoko/openmoko-usb-oui/blob/master/ieee_oui.psv

@peternewman
Copy link
Member

However, I just found out that the ENC28J60 actually also doesn't ship/own a MAC address of its own. So the problem is just the same.

That's a shame, the PIC that Ja-Rule uses has an OUI assigned even if it doesn't have a Phy fitted.

There are suggestions that some of the devices you mention come with a sticker with the MAC set. Although you still need to burn it into the device somehow.

Maybe we could just do as most Desktop Virtualization software does: Have a fixed vendor ID and randomly generate the remaining three bytes. Or use the last three bytes of the Pico's unique ID as the MAC address.

There's also the local bit:
https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local_(U/L_bit)

What would work and would be perfectly legal: https://github.com/openmoko/openmoko-usb-oui/blob/master/ieee_oui.psv

Ah cool, and people grab sensible but reasonable ranges so you can have a few on the same network!

If you grab a block you should record them here:
https://wiki.openlighting.org/index.php/Open_Lighting_Allocations#UIDs

And probably also pick a unique development MAC in the range (mapping to one or a range of development UIDs) which the device boots with if no MAC is set.

I assume a non-W Pico doesn't have a MAC? Equally if someone uses a Pico W but not the wireless bit, could you just borrow the MAC from that? I'd imagine most people won't want to use them simultaneously?

@kripton
Copy link
Member Author

kripton commented Nov 27, 2022

That's a shame, the PIC that Ja-Rule uses has an OUI assigned even if it doesn't have a Phy fitted.

Indeed. There are modules available that contain an EEPROM with a unique MAC but they are of course more expensive. Nice that they ship the PICs with a MAC.

Maybe we could just do as most Desktop Virtualization software does: Have a fixed vendor ID and randomly generate the remaining three bytes. Or use the last three bytes of the Pico's unique ID as the MAC address.

There's also the local bit: https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local_(U/L_bit)

Yep, I was aware and for the USB-Ethernet-Connection we are using it. I fear that some switches might drop those packages but if it proves to work fine, why not? It would at least guarantee that there is no collision with "globally managed MACs".

What would work and would be perfectly legal: https://github.com/openmoko/openmoko-usb-oui/blob/master/ieee_oui.psv

Ah cool, and people grab sensible but reasonable ranges so you can have a few on the same network!

If you grab a block you should record them here: https://wiki.openlighting.org/index.php/Open_Lighting_Allocations#UIDs

Would you say it makes sense to request a range? I'm a bit in doubt there since they can of course only give "small" ranges. And that range might not be sufficient to avoid collisions if there are say 32 devices on the same network?

And probably also pick a unique development MAC in the range (mapping to one or a range of development UIDs) which the device boots with if no MAC is set.

There is a special range for R&D devices at the beginning of their list.

I assume a non-W Pico doesn't have a MAC? Equally if someone uses a Pico W but not the wireless bit, could you just borrow the MAC from that? I'd imagine most people won't want to use them simultaneously?

Right, the non-W Pico doesn't have a MAC. I would assume it would be safe to re-use the wireless MAC for the eth interface (even if probably not allowed). And I want to see the face of the user that first connects the device via WiFi and Ethernet to the same network :D And I'd rather use the same approach for W and non-W Picos to keep it easy. But sure, the idea is valid :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request hardware Anything related to schematics or PCB layouts
Projects
None yet
Development

No branches or pull requests

4 participants