Skip to content
This repository was archived by the owner on Sep 6, 2023. It is now read-only.

Wired Ethernet support #172

Closed
eflukx opened this issue Aug 30, 2017 · 32 comments
Closed

Wired Ethernet support #172

eflukx opened this issue Aug 30, 2017 · 32 comments

Comments

@eflukx
Copy link

eflukx commented Aug 30, 2017

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
Copy link
Contributor

MrSurly commented Aug 30, 2017

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
Copy link
Author

eflukx commented Aug 30, 2017

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
Copy link
Collaborator

nickzoic commented Aug 31, 2017 via email

@MrSurly
Copy link
Contributor

MrSurly commented Aug 31, 2017

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

@eflukx
Copy link
Author

eflukx commented Aug 31, 2017 via email

@eflukx
Copy link
Author

eflukx commented Aug 31, 2017

@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
Copy link
Contributor

MrSurly commented Aug 31, 2017

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
Copy link
Collaborator

nickzoic commented Sep 1, 2017

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
Copy link
Contributor

MrSurly commented Sep 22, 2017

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
Copy link
Collaborator

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
Copy link
Contributor

MrSurly commented Sep 23, 2017

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

Some pitfalls I found during implementation:

  • You have to know your PHY address for the IDF code to work correctly. Both of mine were address 1, using the 8720. The default is 0x1f (31) in sdkconfig. The 8720 can only be 0 or 1, depending on the single address strap pin.
  • I have two PHY's. The "official" WaveShare works fine. Another one, which looks similarly built sorta works. The ESP32 can talk to it, and the link comes up, but the DHCP never offer or ack never occurs, so no IP address. I haven't put it on Wireshark yet, but considering the rest of the HW is the same (I have a 14-pin connector), I suspect the module is just crap.

@dpgeorge
Copy link
Member

dpgeorge commented Sep 25, 2017

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
Copy link
Contributor

MrSurly commented Sep 26, 2017

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
Copy link
Contributor

MrSurly commented Sep 26, 2017

WRT network.AbstractNIC support: Does this seem reasonable?

Support
  • network.LAN(id = None, mdc = machine.Pin(23), mdio = machine.Pin(18), enable = machine.Pin(17), phy_addr = 1, phy_type = network.PHY_LAN8720) This configures the hardware
  • network.active( < is_active > ) Equivalent to ifup or ifdown in Debian parlance
  • network.status() Returns a boolean, based on link status
  • network.ifconfig( < (ip, subnet, gateway, dns) > )
DO NOT support

Or implement as stubs?

  • network.connect()
  • network.disconnect()
  • network.isconnected() Perhaps also returns link status?
  • network.scan()
  • network.config()

@MrSurly
Copy link
Contributor

MrSurly commented Sep 27, 2017

PR #187

@nickzoic
Copy link
Collaborator

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
Copy link
Contributor

MrSurly commented Sep 28, 2017 via email

@nickzoic
Copy link
Collaborator

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

@MrSurly
Copy link
Contributor

MrSurly commented Sep 28, 2017

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
Copy link

fake-name commented Oct 23, 2017

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
Copy link
Member

@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
Copy link
Collaborator

nickzoic commented Oct 23, 2017 via email

@nickzoic
Copy link
Collaborator

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
Copy link

fake-name commented Nov 14, 2017

Will do.

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

@Smeedy
Copy link

Smeedy commented Nov 30, 2017

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
Copy link
Collaborator

nickzoic commented Nov 30, 2017 via email

@Smeedy
Copy link

Smeedy commented Nov 30, 2017

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
Copy link

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

WCYU

@MrSurly
Copy link
Contributor

MrSurly commented Feb 24, 2019

@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
Copy link

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
Copy link
Contributor

MrSurly commented Nov 25, 2020

@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
Copy link

L4bF4b commented Mar 31, 2021

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...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants