This repository was archived by the owner on Sep 6, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 220
Wired ethernet implementation #187
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2016, 2017 Nick Moore @mnemote | ||
* Copyright (c) 2017 "Eric Poulsen" <[email protected]> | ||
* | ||
* Based on esp8266/modnetwork.c which is Copyright (c) 2015 Paul Sokolovsky | ||
* And the ESP IDF example code which is Public Domain / CC0 | ||
|
@@ -48,6 +49,8 @@ | |
#include "lwip/dns.h" | ||
#include "tcpip_adapter.h" | ||
|
||
#include "modnetwork.h" | ||
|
||
#define MODNETWORK_INCLUDE_CONSTANTS (1) | ||
|
||
NORETURN void _esp_exceptions(esp_err_t e) { | ||
|
@@ -122,7 +125,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) { | |
ESP_LOGI("wifi", "STA_START"); | ||
break; | ||
case SYSTEM_EVENT_STA_GOT_IP: | ||
ESP_LOGI("wifi", "GOT_IP"); | ||
ESP_LOGI("network", "GOT_IP"); | ||
break; | ||
case SYSTEM_EVENT_STA_DISCONNECTED: { | ||
// 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) { | |
break; | ||
} | ||
default: | ||
ESP_LOGI("wifi", "event %d", event->event_id); | ||
ESP_LOGI("network", "event %d", event->event_id); | ||
break; | ||
} | ||
return ESP_OK; | ||
|
@@ -182,6 +185,19 @@ STATIC void require_if(mp_obj_t wlan_if, int if_no) { | |
} | ||
|
||
STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) { | ||
static int initialized = 0; | ||
if (!initialized) { | ||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); | ||
ESP_LOGD("modnetwork", "Initializing WiFi"); | ||
ESP_EXCEPTIONS( esp_wifi_init(&cfg) ); | ||
ESP_EXCEPTIONS( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); | ||
ESP_LOGD("modnetwork", "Initialized"); | ||
ESP_EXCEPTIONS( esp_wifi_set_mode(0) ); | ||
ESP_EXCEPTIONS( esp_wifi_start() ); | ||
ESP_LOGD("modnetwork", "Started"); | ||
initialized = 1; | ||
} | ||
|
||
int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : WIFI_IF_STA; | ||
if (idx == WIFI_IF_STA) { | ||
return MP_OBJ_FROM_PTR(&wlan_sta_obj); | ||
|
@@ -201,14 +217,6 @@ STATIC mp_obj_t esp_initialize() { | |
ESP_LOGD("modnetwork", "Initializing Event Loop"); | ||
ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) ); | ||
ESP_LOGD("modnetwork", "esp_event_loop_init done"); | ||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); | ||
ESP_LOGD("modnetwork", "Initializing WiFi"); | ||
ESP_EXCEPTIONS( esp_wifi_init(&cfg) ); | ||
ESP_EXCEPTIONS( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); | ||
ESP_LOGD("modnetwork", "Initialized"); | ||
ESP_EXCEPTIONS( esp_wifi_set_mode(0) ); | ||
ESP_EXCEPTIONS( esp_wifi_start() ); | ||
ESP_LOGD("modnetwork", "Started"); | ||
initialized = 1; | ||
} | ||
return mp_const_none; | ||
|
@@ -358,11 +366,11 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { | |
netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG); | ||
netutils_parse_ipv4_addr(items[3], (void*)&dns_info.ip, NETUTILS_BIG); | ||
// To set a static IP we have to disable DHCP first | ||
if (self->if_id == WIFI_IF_STA) { | ||
esp_err_t e = tcpip_adapter_dhcpc_stop(WIFI_IF_STA); | ||
if (self->if_id == WIFI_IF_STA || self->if_id == ESP_IF_ETH) { | ||
esp_err_t e = tcpip_adapter_dhcpc_stop(self->if_id); | ||
if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e); | ||
ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(WIFI_IF_STA, &info)); | ||
ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(WIFI_IF_STA, TCPIP_ADAPTER_DNS_MAIN, &dns_info)); | ||
ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(self->if_id, &info)); | ||
ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info)); | ||
} else if (self->if_id == WIFI_IF_AP) { | ||
esp_err_t e = tcpip_adapter_dhcps_stop(WIFI_IF_AP); | ||
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) { | |
} | ||
} | ||
|
||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig); | ||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig); | ||
|
||
STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { | ||
if (n_args != 1 && kwargs->used != 0) { | ||
|
@@ -533,6 +541,7 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = { | |
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_initialize_obj }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LAN), (mp_obj_t)&get_lan_obj }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj }, | ||
|
||
#if MODNETWORK_INCLUDE_CONSTANTS | ||
|
@@ -560,6 +569,11 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = { | |
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA_WPA2_PSK) }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_MAX), | ||
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_MAX) }, | ||
|
||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PHY_LAN8720), | ||
MP_OBJ_NEW_SMALL_INT(PHY_LAN8720) }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PHY_TLK110), | ||
MP_OBJ_NEW_SMALL_INT(PHY_TLK110) }, | ||
#endif | ||
}; | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* This file is part of the MicroPython project, http://micropython.org/ | ||
* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2017 "Eric Poulsen" <[email protected]> | ||
* | ||
* Based on the ESP IDF example code which is Public Domain / CC0 | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
#ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H | ||
#define MICROPY_INCLUDED_ESP32_MODNETWORK_H | ||
|
||
enum { PHY_LAN8720, PHY_TLK110 }; | ||
MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj); | ||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj); | ||
|
||
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
/* | ||
* This file is part of the MicroPython project, http://micropython.org/ | ||
* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2017 "Eric Poulsen" <[email protected]> | ||
* | ||
* Based on the ESP IDF example code which is Public Domain / CC0 | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
#include "py/runtime.h" | ||
#include "py/mphal.h" | ||
|
||
#include "eth_phy/phy.h" | ||
#include "eth_phy/phy_tlk110.h" | ||
#include "eth_phy/phy_lan8720.h" | ||
#include "tcpip_adapter.h" | ||
|
||
#include "modnetwork.h" | ||
|
||
typedef struct _lan_if_obj_t { | ||
mp_obj_base_t base; | ||
int if_id; // MUST BE FIRST to match wlan_if_obj_t | ||
bool initialized; | ||
bool active; | ||
uint8_t mdc_pin; | ||
uint8_t mdio_pin; | ||
int8_t phy_power_pin; | ||
uint8_t phy_addr; | ||
uint8_t phy_type; | ||
eth_phy_check_link_func link_func; | ||
eth_phy_power_enable_func power_func; | ||
} lan_if_obj_t; | ||
|
||
const mp_obj_type_t lan_if_type; | ||
STATIC lan_if_obj_t lan_obj = {{&lan_if_type}, ESP_IF_ETH, false, false}; | ||
|
||
STATIC void phy_power_enable(bool enable) { | ||
lan_if_obj_t* self = &lan_obj; | ||
|
||
if (self->phy_power_pin != -1) { | ||
|
||
if (!enable) { | ||
// Do the PHY-specific power_enable(false) function before powering down | ||
self->power_func(false); | ||
} | ||
|
||
gpio_pad_select_gpio(self->phy_power_pin); | ||
gpio_set_direction(self->phy_power_pin, GPIO_MODE_OUTPUT); | ||
if (enable) { | ||
gpio_set_level(self->phy_power_pin, 1); | ||
} else { | ||
gpio_set_level(self->phy_power_pin, 0); | ||
} | ||
|
||
// Allow the power up/down to take effect, min 300us | ||
vTaskDelay(1); | ||
|
||
if (enable) { | ||
// Run the PHY-specific power on operations now the PHY has power | ||
self->power_func(true); | ||
} | ||
} | ||
} | ||
|
||
STATIC void init_lan_rmii() { | ||
lan_if_obj_t* self = &lan_obj; | ||
phy_rmii_configure_data_interface_pins(); | ||
phy_rmii_smi_configure_pins(self->mdc_pin, self->mdio_pin); | ||
} | ||
|
||
STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { | ||
lan_if_obj_t* self = &lan_obj; | ||
|
||
if (self->initialized) { | ||
return MP_OBJ_FROM_PTR(&lan_obj); | ||
} | ||
|
||
enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type }; | ||
|
||
|
||
static const mp_arg_t allowed_args[] = { | ||
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, | ||
{ MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||
{ MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||
{ MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, | ||
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, | ||
}; | ||
|
||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; | ||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); | ||
|
||
if (args[ARG_id].u_obj != mp_const_none) { | ||
if (mp_obj_get_int(args[ARG_id].u_obj) != 0) { | ||
mp_raise_ValueError("invalid LAN interface identifier"); | ||
} | ||
} | ||
|
||
self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj); | ||
self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj); | ||
self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj); | ||
|
||
if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) { | ||
mp_raise_ValueError("invalid phy address"); | ||
} | ||
|
||
if (args[ARG_phy_type].u_int != PHY_LAN8720 && args[ARG_phy_type].u_int != PHY_TLK110) { | ||
mp_raise_ValueError("invalid phy type"); | ||
} | ||
|
||
|
||
eth_config_t config; | ||
|
||
switch (args[ARG_phy_type].u_int) { | ||
case PHY_TLK110: | ||
config = phy_tlk110_default_ethernet_config; | ||
break; | ||
case PHY_LAN8720: | ||
config = phy_lan8720_default_ethernet_config; | ||
break; | ||
} | ||
|
||
self->link_func = config.phy_check_link; | ||
|
||
// Replace default power func with our own | ||
self->power_func = config.phy_power_enable; | ||
config.phy_power_enable = phy_power_enable; | ||
|
||
config.phy_addr = args[ARG_phy_addr].u_int; | ||
config.gpio_config = init_lan_rmii; | ||
config.tcpip_input = tcpip_adapter_eth_input; | ||
|
||
if (esp_eth_init(&config) == ESP_OK) { | ||
self->active = false; | ||
self->initialized = true; | ||
} else { | ||
mp_raise_msg(&mp_type_OSError, "esp_eth_init() failed"); | ||
} | ||
return MP_OBJ_FROM_PTR(&lan_obj); | ||
} | ||
MP_DEFINE_CONST_FUN_OBJ_KW(get_lan_obj, 0, get_lan); | ||
|
||
STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) { | ||
lan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); | ||
|
||
if (n_args > 1) { | ||
if (mp_obj_is_true(args[1])) { | ||
self->active = (esp_eth_enable() == ESP_OK); | ||
if (!self->active) { | ||
mp_raise_msg(&mp_type_OSError, "ethernet enable failed"); | ||
} | ||
} else { | ||
self->active = !(esp_eth_disable() == ESP_OK); | ||
if (self->active) { | ||
mp_raise_msg(&mp_type_OSError, "ethernet disable failed"); | ||
} | ||
} | ||
} | ||
return mp_obj_new_bool(self->active); | ||
} | ||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lan_active_obj, 1, 2, lan_active); | ||
|
||
STATIC mp_obj_t lan_status(mp_obj_t self_in) { | ||
return mp_const_none; | ||
} | ||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_status_obj, lan_status); | ||
|
||
STATIC mp_obj_t lan_isconnected(mp_obj_t self_in) { | ||
lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); | ||
return self->active ? mp_obj_new_bool(self->link_func()) : mp_const_false; | ||
} | ||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_isconnected_obj, lan_isconnected); | ||
|
||
STATIC const mp_map_elem_t lan_if_locals_dict_table[] = { | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_active), (mp_obj_t)&lan_active_obj }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&lan_isconnected_obj }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&lan_status_obj }, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&esp_ifconfig_obj }, | ||
}; | ||
|
||
STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table); | ||
|
||
const mp_obj_type_t lan_if_type = { | ||
{ &mp_type_type }, | ||
.name = MP_QSTR_LAN, | ||
.locals_dict = (mp_obj_dict_t*)&lan_if_locals_dict, | ||
}; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the constants be prefixed with something like ETH or LAN to emphasise that they are for wired and not wifi?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the hardware in question is a PHY, thus the PHY prefix -- this should stay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it's specifically a wired LAN PHY, as opposed to a wireless/USB/etc PHY. So I was thinking something like ETH_PHY_LAN8720.