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

Commit fa3b1fe

Browse files
MrSurlydpgeorge
authored andcommitted
esp32: Implement wired Ethernet via network.LAN().
Updates to Makefile, modnetwork.c, and addition of network_lan.c to implement `network.LAN()` object for wired PHY objects.
1 parent eae6526 commit fa3b1fe

File tree

4 files changed

+270
-15
lines changed

4 files changed

+270
-15
lines changed

ports/esp32/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ SRC_C = \
136136
machine_uart.c \
137137
modmachine.c \
138138
modnetwork.c \
139+
network_lan.c \
139140
modsocket.c \
140141
modesp.c \
141142
moduhashlib.c \
@@ -267,6 +268,9 @@ ESPIDF_CXX_O = $(addprefix $(ESPCOMP)/cxx/,\
267268
ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\
268269
emac_dev.o \
269270
emac_main.o \
271+
eth_phy/phy_tlk110.o \
272+
eth_phy/phy_lan8720.o \
273+
eth_phy/phy_common.o \
270274
)
271275

272276
$(BUILD)/$(ESPCOMP)/expat/%.o: CFLAGS += -Wno-unused-function

ports/esp32/modnetwork.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* The MIT License (MIT)
88
*
99
* Copyright (c) 2016, 2017 Nick Moore @mnemote
10+
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
1011
*
1112
* Based on esp8266/modnetwork.c which is Copyright (c) 2015 Paul Sokolovsky
1213
* And the ESP IDF example code which is Public Domain / CC0
@@ -48,6 +49,8 @@
4849
#include "lwip/dns.h"
4950
#include "tcpip_adapter.h"
5051

52+
#include "modnetwork.h"
53+
5154
#define MODNETWORK_INCLUDE_CONSTANTS (1)
5255

5356
NORETURN void _esp_exceptions(esp_err_t e) {
@@ -122,7 +125,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) {
122125
ESP_LOGI("wifi", "STA_START");
123126
break;
124127
case SYSTEM_EVENT_STA_GOT_IP:
125-
ESP_LOGI("wifi", "GOT_IP");
128+
ESP_LOGI("network", "GOT_IP");
126129
break;
127130
case SYSTEM_EVENT_STA_DISCONNECTED: {
128131
// This is a workaround as ESP32 WiFi libs don't currently
@@ -161,7 +164,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) {
161164
break;
162165
}
163166
default:
164-
ESP_LOGI("wifi", "event %d", event->event_id);
167+
ESP_LOGI("network", "event %d", event->event_id);
165168
break;
166169
}
167170
return ESP_OK;
@@ -182,6 +185,19 @@ STATIC void require_if(mp_obj_t wlan_if, int if_no) {
182185
}
183186

184187
STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
188+
static int initialized = 0;
189+
if (!initialized) {
190+
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
191+
ESP_LOGD("modnetwork", "Initializing WiFi");
192+
ESP_EXCEPTIONS( esp_wifi_init(&cfg) );
193+
ESP_EXCEPTIONS( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
194+
ESP_LOGD("modnetwork", "Initialized");
195+
ESP_EXCEPTIONS( esp_wifi_set_mode(0) );
196+
ESP_EXCEPTIONS( esp_wifi_start() );
197+
ESP_LOGD("modnetwork", "Started");
198+
initialized = 1;
199+
}
200+
185201
int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : WIFI_IF_STA;
186202
if (idx == WIFI_IF_STA) {
187203
return MP_OBJ_FROM_PTR(&wlan_sta_obj);
@@ -201,14 +217,6 @@ STATIC mp_obj_t esp_initialize() {
201217
ESP_LOGD("modnetwork", "Initializing Event Loop");
202218
ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) );
203219
ESP_LOGD("modnetwork", "esp_event_loop_init done");
204-
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
205-
ESP_LOGD("modnetwork", "Initializing WiFi");
206-
ESP_EXCEPTIONS( esp_wifi_init(&cfg) );
207-
ESP_EXCEPTIONS( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
208-
ESP_LOGD("modnetwork", "Initialized");
209-
ESP_EXCEPTIONS( esp_wifi_set_mode(0) );
210-
ESP_EXCEPTIONS( esp_wifi_start() );
211-
ESP_LOGD("modnetwork", "Started");
212220
initialized = 1;
213221
}
214222
return mp_const_none;
@@ -358,11 +366,11 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
358366
netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG);
359367
netutils_parse_ipv4_addr(items[3], (void*)&dns_info.ip, NETUTILS_BIG);
360368
// To set a static IP we have to disable DHCP first
361-
if (self->if_id == WIFI_IF_STA) {
362-
esp_err_t e = tcpip_adapter_dhcpc_stop(WIFI_IF_STA);
369+
if (self->if_id == WIFI_IF_STA || self->if_id == ESP_IF_ETH) {
370+
esp_err_t e = tcpip_adapter_dhcpc_stop(self->if_id);
363371
if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e);
364-
ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(WIFI_IF_STA, &info));
365-
ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(WIFI_IF_STA, TCPIP_ADAPTER_DNS_MAIN, &dns_info));
372+
ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(self->if_id, &info));
373+
ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info));
366374
} else if (self->if_id == WIFI_IF_AP) {
367375
esp_err_t e = tcpip_adapter_dhcps_stop(WIFI_IF_AP);
368376
if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e);
@@ -374,7 +382,7 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
374382
}
375383
}
376384

377-
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
385+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
378386

379387
STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
380388
if (n_args != 1 && kwargs->used != 0) {
@@ -533,6 +541,7 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
533541
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
534542
{ MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_initialize_obj },
535543
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj },
544+
{ MP_OBJ_NEW_QSTR(MP_QSTR_LAN), (mp_obj_t)&get_lan_obj },
536545
{ MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj },
537546

538547
#if MODNETWORK_INCLUDE_CONSTANTS
@@ -560,6 +569,11 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
560569
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA_WPA2_PSK) },
561570
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_MAX),
562571
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_MAX) },
572+
573+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PHY_LAN8720),
574+
MP_OBJ_NEW_SMALL_INT(PHY_LAN8720) },
575+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PHY_TLK110),
576+
MP_OBJ_NEW_SMALL_INT(PHY_TLK110) },
563577
#endif
564578
};
565579

ports/esp32/modnetwork.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
#ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H
27+
#define MICROPY_INCLUDED_ESP32_MODNETWORK_H
28+
29+
enum { PHY_LAN8720, PHY_TLK110 };
30+
31+
MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj);
32+
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj);
33+
34+
#endif

ports/esp32/network_lan.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
7+
*
8+
* Based on the ESP IDF example code which is Public Domain / CC0
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*/
28+
29+
#include "py/runtime.h"
30+
#include "py/mphal.h"
31+
32+
#include "eth_phy/phy.h"
33+
#include "eth_phy/phy_tlk110.h"
34+
#include "eth_phy/phy_lan8720.h"
35+
#include "tcpip_adapter.h"
36+
37+
#include "modnetwork.h"
38+
39+
typedef struct _lan_if_obj_t {
40+
mp_obj_base_t base;
41+
int if_id; // MUST BE FIRST to match wlan_if_obj_t
42+
bool initialized;
43+
bool active;
44+
uint8_t mdc_pin;
45+
uint8_t mdio_pin;
46+
int8_t phy_power_pin;
47+
uint8_t phy_addr;
48+
uint8_t phy_type;
49+
eth_phy_check_link_func link_func;
50+
eth_phy_power_enable_func power_func;
51+
} lan_if_obj_t;
52+
53+
const mp_obj_type_t lan_if_type;
54+
STATIC lan_if_obj_t lan_obj = {{&lan_if_type}, ESP_IF_ETH, false, false};
55+
56+
STATIC void phy_power_enable(bool enable) {
57+
lan_if_obj_t* self = &lan_obj;
58+
59+
if (self->phy_power_pin != -1) {
60+
61+
if (!enable) {
62+
// Do the PHY-specific power_enable(false) function before powering down
63+
self->power_func(false);
64+
}
65+
66+
gpio_pad_select_gpio(self->phy_power_pin);
67+
gpio_set_direction(self->phy_power_pin, GPIO_MODE_OUTPUT);
68+
if (enable) {
69+
gpio_set_level(self->phy_power_pin, 1);
70+
} else {
71+
gpio_set_level(self->phy_power_pin, 0);
72+
}
73+
74+
// Allow the power up/down to take effect, min 300us
75+
vTaskDelay(1);
76+
77+
if (enable) {
78+
// Run the PHY-specific power on operations now the PHY has power
79+
self->power_func(true);
80+
}
81+
}
82+
}
83+
84+
STATIC void init_lan_rmii() {
85+
lan_if_obj_t* self = &lan_obj;
86+
phy_rmii_configure_data_interface_pins();
87+
phy_rmii_smi_configure_pins(self->mdc_pin, self->mdio_pin);
88+
}
89+
90+
STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
91+
lan_if_obj_t* self = &lan_obj;
92+
93+
if (self->initialized) {
94+
return MP_OBJ_FROM_PTR(&lan_obj);
95+
}
96+
97+
enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type };
98+
static const mp_arg_t allowed_args[] = {
99+
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} },
100+
{ MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
101+
{ MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
102+
{ MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
103+
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
104+
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
105+
};
106+
107+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
108+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
109+
110+
if (args[ARG_id].u_obj != mp_const_none) {
111+
if (mp_obj_get_int(args[ARG_id].u_obj) != 0) {
112+
mp_raise_ValueError("invalid LAN interface identifier");
113+
}
114+
}
115+
116+
self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj);
117+
self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj);
118+
self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj);
119+
120+
if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) {
121+
mp_raise_ValueError("invalid phy address");
122+
}
123+
124+
if (args[ARG_phy_type].u_int != PHY_LAN8720 && args[ARG_phy_type].u_int != PHY_TLK110) {
125+
mp_raise_ValueError("invalid phy type");
126+
}
127+
128+
eth_config_t config;
129+
130+
switch (args[ARG_phy_type].u_int) {
131+
case PHY_TLK110:
132+
config = phy_tlk110_default_ethernet_config;
133+
break;
134+
case PHY_LAN8720:
135+
config = phy_lan8720_default_ethernet_config;
136+
break;
137+
}
138+
139+
self->link_func = config.phy_check_link;
140+
141+
// Replace default power func with our own
142+
self->power_func = config.phy_power_enable;
143+
config.phy_power_enable = phy_power_enable;
144+
145+
config.phy_addr = args[ARG_phy_addr].u_int;
146+
config.gpio_config = init_lan_rmii;
147+
config.tcpip_input = tcpip_adapter_eth_input;
148+
149+
if (esp_eth_init(&config) == ESP_OK) {
150+
self->active = false;
151+
self->initialized = true;
152+
} else {
153+
mp_raise_msg(&mp_type_OSError, "esp_eth_init() failed");
154+
}
155+
return MP_OBJ_FROM_PTR(&lan_obj);
156+
}
157+
MP_DEFINE_CONST_FUN_OBJ_KW(get_lan_obj, 0, get_lan);
158+
159+
STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) {
160+
lan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
161+
162+
if (n_args > 1) {
163+
if (mp_obj_is_true(args[1])) {
164+
self->active = (esp_eth_enable() == ESP_OK);
165+
if (!self->active) {
166+
mp_raise_msg(&mp_type_OSError, "ethernet enable failed");
167+
}
168+
} else {
169+
self->active = !(esp_eth_disable() == ESP_OK);
170+
if (self->active) {
171+
mp_raise_msg(&mp_type_OSError, "ethernet disable failed");
172+
}
173+
}
174+
}
175+
return mp_obj_new_bool(self->active);
176+
}
177+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lan_active_obj, 1, 2, lan_active);
178+
179+
STATIC mp_obj_t lan_status(mp_obj_t self_in) {
180+
return mp_const_none;
181+
}
182+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_status_obj, lan_status);
183+
184+
STATIC mp_obj_t lan_isconnected(mp_obj_t self_in) {
185+
lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
186+
return self->active ? mp_obj_new_bool(self->link_func()) : mp_const_false;
187+
}
188+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_isconnected_obj, lan_isconnected);
189+
190+
STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = {
191+
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&lan_active_obj) },
192+
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&lan_isconnected_obj) },
193+
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) },
194+
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
195+
};
196+
197+
STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table);
198+
199+
const mp_obj_type_t lan_if_type = {
200+
{ &mp_type_type },
201+
.name = MP_QSTR_LAN,
202+
.locals_dict = (mp_obj_dict_t*)&lan_if_locals_dict,
203+
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy