micropython / micropython-esp32

Old port of MicroPython to the ESP32 -- new port is at https://github.com/micropython/micropython
MIT License
673 stars 216 forks source link

Wired Ethernet support #172

Closed eflukx closed 6 years ago

eflukx commented 7 years ago

Is there any development going on or planned in this area? If not, what would be best the approach to enable support for wired ethernet in micropyhton?

Some ideas/ponderings:

Would simply wrapping the C API available for wired ethernet (MII) in esp-idf do the job? Is micropython using the tcp/ip stack from the IDF or has it implemented a 'local' network stack (and how would these interact/interfere)? How would using the ethernet API from idf play nicely with the WiFi capabilities available within micropython?

Another possible approach would be to handle the wired connection management in a separate task, outside of the micropython rtos task. Would this be a feasable approach?

A lot of quesitons, but I would like to have a go at obtaining ethernet support from within micropython on the ESP32 one way or the other. Any handles to do so are most welcome!

MrSurly commented 7 years ago

I have a need for this for an upcoming project, and I'd be willing to take on development.

Sounds as if you've already implemented this in C?

I actually have the hardware (ethernet PHY board), bought based on the information found on this page.

eflukx commented 7 years ago

I also have the hardware to play around with this (ESP32-WROOM + lan8720a phy board). I had a go with hooking the hardware up and play around with the ethernet example in the esp-idf.

Edit: Yes I found the same page, with the good work from Frank Sauter. Will mod my PHY board tomorrow. I think first step is to get the hardware working.

Getting this to run in the C/idf world should not be too hard, all hard work (specifically for getting my phy to run with ESP32) seems to be done on the esp-idf source tree already.

How micropython interacts with the esp-idf sdk, specifically the network parts, is unclear to me.

nickzoic commented 7 years ago

G'day Rogier,

Yep, the MicroPython API would just wrap the existing ESP-IDF functionality, just cleaning it up a little to make it look more Pythonic. Have a look at the source for "esp32/modnetwork.c" as an example: functions like "esp_active" just wrap the underlying esp_wifi_set_mode function into a form more appropriate for calling from Python. The rest of the networking stack is implemented the same way, eg: "modsocket.c" just wraps underlying ESP-IDF functions as well. The exposed API should be as close as possible to that on other MicroPython platforms so that code is portable cross-platform with minimum pain. I just ordered in a LAN8720 PHY module for testing :-)

MrSurly commented 6 years ago

@nickzoic Are there any other MicroPython platforms that have an ethernet interface?

eflukx commented 6 years ago

Edit: Oops, Misread the question, @MrSurly was asking for other platforms with ethernet. Leaving comment for educational purposes.

The ESP32 has an Ethernet MAC on the die. The external interface is called a (R)MII interface, which is a standard interface for ethernet adapters. To obtain a normal (UTP) ethernet interface a 'PHY'-chip and some magnetics (transformers, typically built right into the RJ45 socket) needs to be added.

For instance the LAN8720 PHY is supported by the ESP-IDF SDK and can be easily obtained as a module on Ebay for a couple of dollars. In one of the earlier comments on this issue thread, there is a link to a page where it is explained how to hook it all up. Once you've hooked up your PHY board, you have a RJ45 plug to you avail!

eflukx commented 6 years ago

@MrSurly There is a driver for the Wiznet W5500 in the micropyhton source tree (https://github.com/micropython/micropython/tree/master/drivers/wiznet5k).

The Wiznet module provides ethernet as well, but also implements a TCP/IP stack right on the silicon. However, I don't know how this API is exposed in MP.

MrSurly commented 6 years ago

The Wiznet module provides ethernet as well, but also implements a TCP/IP stack right on the silicon. However, I don't know how this API is exposed in MP.

@eflukx I'll look at the source for that one, thanks.

nickzoic commented 6 years ago

Dunno if you'll get a lot from the source ... it's a very different beast ... but the interface once constructed should be mostly interchangable with the WIZNET5K() instance and also the ESP32's existing network.WLAN() instance, that way a programmer can use them interchangeably even if the construction details are different.

MrSurly commented 6 years ago

Okay, I'm moving forward with this. I have the HW working, using the IDF ethernet example.

@nickzoic I'm wondering about proper implementation of the namespace (e.g. network.LAN ? ) and API. Perhaps something like this:

import network
l = network.LAN()
l.init(mdc = machine.Pin(23), mdio = machine.Pin(18), enable = machine.Pin(17), phy_adx = 1) ## set MDC/MDIO/Enable pins and phy address. Probably default all of them to these values.
l.ifconfig() # Same as WLAN
l.mac() # Same as WLAN -- not sure if it can be set
l.isconnected() # If ETH link is detected
l.deinit() # Shutdown 

Also need

nickzoic commented 6 years ago

That would make sense to me: it should provide everything under network.AbstractNIC so that you could easily write code which takes an initted "network.LAN" object or an initted "network.WLAN" object (or even a network.SLIP, for example) and treats them the same.

My hardware still hasn't arrived, but should be here soon ...

MrSurly commented 6 years ago

Ah, okay, hadn't seen network.AbstractNIC yet.

Some pitfalls I found during implementation:

dpgeorge commented 6 years ago

it should provide everything under network.AbstractNIC so that you could easily write code which takes an initted "network.LAN" object or an initted "network.WLAN" object (or even a network.SLIP, for example) and treats them the same.

Yes, exactly!

Calling it network.LAN() sounds good, otherwise network.Ethernet() would be more specific but longer to type (and pretty much all LAN's are Ethernet based anyway).

You have to know your PHY address for the IDF code to work correctly.

Can it be configured dynamically at runtime or must it be done at compile time? If the latter then that's quite limiting...

MrSurly commented 6 years ago

Can it be configured dynamically at runtime or must it be done at compile time? If the latter then that's quite limiting...

Looks like it can be configured at runtime. Yay!

MrSurly commented 6 years ago

WRT network.AbstractNIC support: Does this seem reasonable?

Support
DO NOT support

Or implement as stubs?

MrSurly commented 6 years ago

PR https://github.com/micropython/micropython-esp32/pull/187

nickzoic commented 6 years ago

Yes, I think isconnected() should return the link status as boolean...

Whereas status() isn't really well thought through yet (but I'd rather it be a more structured thing as per my comments in #186)

I'm still waiting on hardware but it should arrive soon, as soon as it does I'll test!

MrSurly commented 6 years ago

I agree. I'll change it to isconnected tomorrow.

On Sep 27, 2017 17:45, "Nick Moore" notifications@github.com wrote:

Yes, I think isconnected() should return the link status as boolean...

Whereas status() isn't really well thought through yet (but I'd rather it be a more structured thing as per my comments in #186 https://github.com/micropython/micropython-esp32/issues/186)

I'm still waiting on hardware but it should arrive soon, as soon as it does I'll test!

nickzoic commented 6 years ago

I've got the 8720 on the way, but has anyone found a good source for TLK110 breakouts online?

MrSurly commented 6 years ago

TLK110 breakouts online

I tried looking, but only found that TI eval board. Also, some of the discussions on the IDF forum has users asking which TLK110 hardware was used.

Are you getting the [Waveshare}(https://www.waveshare.com/lan8720-eth-board.htm) board? I have another board that (basically) looks the same but doesn't really work well, but the WaveShare works fine.

fake-name commented 6 years ago

If anyone isn't aware, Olimex has several boards with wired-ethernet:

The ESP32-GATEWAY is especially interesting, as it doesn't have much else on the board. It's also nice as it's available on amazon prime: http://a.co/bnafDqH for $30 dollars.

It has a LAN8710A-EZC on it.

I'd happily buy a couple for people if it'd help get support implemented.

dpgeorge commented 6 years ago

@fake-name once generic support for Ethernet lands (which is what is being worked on now) then it should be pretty easy (probably trivial, just 1 line of Python) to support the Olimex boads.

nickzoic commented 6 years ago

Is there support for that particular chip in the ESP-IDF? If so it'll be very easy to add it to the existing PR.Or it might be close enough to just work with the 8720 code, I don't know.

nickzoic commented 6 years ago

Closed by PR #187 ... thanks @MrSurly!

@fake-name, can you try it out with an Olimex board? The 8710A might be close enough in API to the 8720 to just work, or if it doesn't work please open a new issue and we'll work on it there.

fake-name commented 6 years ago

Will do.

I may not get time until this coming weekend, though.

Smeedy commented 6 years ago

Hi there. I just got my hands on an Olimex ESP32-GATEWAY with the LAN8710A-EZC. Managed to get the ethernet example running from ESP-IDF, be it that it is a little flaky obtaining a DHCP address.

I was giving it a poke with the esp32-20171129-v1.9.2-445-g84035f0f.bin firmware, and I fiddled around using some hint from this topic and the source from Github. Seems like a silly question, but where can I find the proper docs for the network_lan?

Thx, Martijn

nickzoic commented 6 years ago

Oh, that's great that it just works straight out of the box! (could you test the DHCP thing a bit more and let us know what kind of flakey?) The docs need some catching up. Pull requests welcome!

Smeedy commented 6 years ago

Ah the documentation! Good code is always self-documenting :)

The flaky part is when I use the example from the ESP-IDF and flash it to the ESP32-GATEWAY it doesn't seem to pick up an address. Giving it a hard reset using button or power cycle, same problem. But when I do a make monitor from the prompt the device seems to soft-reset and all in a sudden it is picking up addresses when I (re)connect an ethernet cable.

So I'll need to do some testing as this board will be doing some C/C++ RTOS tasking eventually in an environment where I cannot use WiFI.

On topic. Running ethernet on the ESP32-GATEWAY using the esp32-20171129-v1.9.2-445-g84035f0f.binfirmware seems to work right out the box:

>>> import machine
>>> import network
>>> l = network.LAN(mdc = machine.Pin(23), mdio = machine.Pin(18), power = machine.Pin(17), phy_type = network.PHY_LAN8720, phy_addr=0)
 I (18599) emac: mac version 1137a
>>> l.ifconfig()
('0.0.0.0', '0.0.0.0', '0.0.0.0', '0.0.0.0')
>>> l.active(1)
I (62929) emac: emac start !!!

I (62929) emac: emac resetting ....
I (62929) emac: emac reset done
I (62929) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (62949) emac: emac start success !!!
I (62949) network: event 19
True

### this is where I plug in the cable

>>> I (66949) emac: eth link_up!!!
I (66949) network: event 21
I (68939) event: eth ip: 172.30.1.107, mask: 255.255.255.0, gw: 172.30.1.1
I (68939) network: event 23

>>> l.ifconfig()
('172.30.1.107', '255.255.255.0', '172.30.1.1', '172.30.1.1')

Can ping it from the LAN, so this looks to be working fine.

Great show guys, Thx

wcyu1205 commented 5 years ago

HI Smeedy, Where to get the firmware you mentioned? How to update the firmware with ESP-IDF?

WCYU

MrSurly commented 5 years ago

@wcyu1205 This repository (which is ESP32 specific) is deprecated. This code has all been merged into the main repository, follow the normal method for putting the firmware onto your device.

RakibFiha commented 3 years ago

Ah the documentation! Good code is always self-documenting :)

The flaky part is when I use the example from the ESP-IDF and flash it to the ESP32-GATEWAY it doesn't seem to pick up an address. Giving it a hard reset using button or power cycle, same problem. But when I do a make monitor from the prompt the device seems to soft-reset and all in a sudden it is picking up addresses when I (re)connect an ethernet cable.

So I'll need to do some testing as this board will be doing some C/C++ RTOS tasking eventually in an environment where I cannot use WiFI.

On topic. Running ethernet on the ESP32-GATEWAY using the esp32-20171129-v1.9.2-445-g84035f0f.binfirmware seems to work right out the box:

>>> import machine
>>> import network
>>> l = network.LAN(mdc = machine.Pin(23), mdio = machine.Pin(18), power = machine.Pin(17), phy_type = network.PHY_LAN8720, phy_addr=0)
 I (18599) emac: mac version 1137a
>>> l.ifconfig()
('0.0.0.0', '0.0.0.0', '0.0.0.0', '0.0.0.0')
>>> l.active(1)
I (62929) emac: emac start !!!

I (62929) emac: emac resetting ....
I (62929) emac: emac reset done
I (62929) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (62949) emac: emac start success !!!
I (62949) network: event 19
True

### this is where I plug in the cable

>>> I (66949) emac: eth link_up!!!
I (66949) network: event 21
I (68939) event: eth ip: 172.30.1.107, mask: 255.255.255.0, gw: 172.30.1.1
I (68939) network: event 23

>>> l.ifconfig()
('172.30.1.107', '255.255.255.0', '172.30.1.1', '172.30.1.1')

Can ping it from the LAN, so this looks to be working fine.

Great show guys, Thx

Where is the network.LAN attribute in the latest micropython ?

MrSurly commented 3 years ago

@RakibFiha This is a deprecated repository. The correct repo for MP is https://github.com/micropython/micropython

Having said that, if you look at modnetwork.c for the current head of MicroPython, it relies on IDF version != 4. Not sure what version of the IDF you're compiling against (or if you even are compiling it yourself), but this might help.

#if !MICROPY_ESP_IDF_4
{ MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) },
#endif
L4bF4b commented 3 years ago

i have the same problem, it was a hard job to compile it unchanged following the github-instructions myself.

But where to make the changes?

original lines in modnetwork.c

#if !MICROPY_ESP_IDF_4
#include "esp_wifi_types.h"
#include "esp_event_loop.h"
#include "esp_wifi_types.h"
#include "esp_event_loop.h"
#endif

i tried Version 1:

#if !MICROPY_ESP_IDF_4
{ MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) },
#endif

i tried Version 2:

#if !MICROPY_ESP_IDF_4
{ MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) },
 #include "esp_wifi_types.h"
 #include "esp_event_loop.h"
#endif

export.sh --> Build Firmware --> but no effect. network.LAN is not enabled...