-
-
Notifications
You must be signed in to change notification settings - Fork 345
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Ethernet support for ESP32 (#2361)
This PR aims to provide generic Ethernet support for Sming. Initially this is for the ESP32 using its embedded MAC. Note that Sming ESP32 requires a patched version of ESP IDF version 4.3. See #2358.
- Loading branch information
Showing
22 changed files
with
1,103 additions
and
9 deletions.
There are no files selected for viewing
This file contains 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 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 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 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
239 changes: 239 additions & 0 deletions
239
Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp
This file contains 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,239 @@ | ||
/**** | ||
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. | ||
* Created 2015 by Skurydin Alexey | ||
* http://github.com/SmingHub/Sming | ||
* All files of the Sming Core are provided under the LGPL v3 license. | ||
* | ||
* EmbeddedEthernet.cpp | ||
* | ||
****/ | ||
|
||
#include <Platform/EmbeddedEthernet.h> | ||
// #include <freertos/event_groups.h> | ||
#include <esp_eth.h> | ||
#include <esp_event.h> | ||
#include <driver/gpio.h> | ||
|
||
using namespace Ethernet; | ||
|
||
bool EmbeddedEthernet::begin(const Config& config) | ||
{ | ||
#if !CONFIG_ETH_USE_ESP32_EMAC | ||
|
||
debug_e("[ETH] Internal MAC not available"); | ||
return false; | ||
|
||
#else | ||
|
||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); | ||
netif = esp_netif_new(&cfg); | ||
|
||
// Set default handlers to process TCP/IP stuffs | ||
ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif)); | ||
|
||
// And register our own event handlers | ||
enableEventCallback(true); | ||
enableGotIpCallback(true); | ||
|
||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); | ||
if(config.mac.smiMdcPin != PIN_DEFAULT) { | ||
mac_config.smi_mdc_gpio_num = config.mac.smiMdcPin; | ||
} | ||
if(config.mac.smiMdioPin != PIN_DEFAULT) { | ||
mac_config.smi_mdio_gpio_num = config.mac.smiMdioPin; | ||
} | ||
mac = esp_eth_mac_new_esp32(&mac_config); | ||
if(mac == nullptr) { | ||
debug_e("[ETH] Failed to construct MAC"); | ||
return false; | ||
} | ||
|
||
phy = reinterpret_cast<esp_eth_phy_t*>(phyFactory.create(config.phy)); | ||
if(phy == nullptr) { | ||
debug_e("[ETH] Failed to construct PHY"); | ||
return false; | ||
} | ||
|
||
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); | ||
ESP_ERROR_CHECK(esp_eth_driver_install(ð_config, &handle)); | ||
netif_glue = esp_eth_new_netif_glue(handle); | ||
ESP_ERROR_CHECK(esp_netif_attach(netif, netif_glue)); | ||
ESP_ERROR_CHECK(esp_eth_start(handle)); | ||
|
||
return true; | ||
#endif | ||
} | ||
|
||
void EmbeddedEthernet::end() | ||
{ | ||
if(handle == nullptr) { | ||
return; | ||
} | ||
|
||
ESP_ERROR_CHECK(esp_eth_stop(handle)); | ||
ESP_ERROR_CHECK(esp_eth_del_netif_glue(netif_glue)); | ||
netif_glue = nullptr; | ||
ESP_ERROR_CHECK(esp_eth_clear_default_handlers(netif)); | ||
|
||
ESP_ERROR_CHECK(esp_eth_driver_uninstall(handle)); | ||
handle = nullptr; | ||
|
||
phyFactory.destroy(reinterpret_cast<PhyInstance*>(phy)); | ||
phy = nullptr; | ||
|
||
ESP_ERROR_CHECK(mac->del(mac)); | ||
mac = nullptr; | ||
|
||
esp_netif_destroy(netif); | ||
netif = nullptr; | ||
|
||
enableEventCallback(false); | ||
enableGotIpCallback(false); | ||
} | ||
|
||
void EmbeddedEthernet::enableEventCallback(bool enable) | ||
{ | ||
auto handler = [](void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { | ||
auto ethernet = static_cast<EmbeddedEthernet*>(arg); | ||
ethernet->state = Event(event_id); | ||
if(!ethernet->eventCallback) { | ||
return; | ||
} | ||
ethernet->eventCallback(Event(event_id)); | ||
}; | ||
|
||
if(enable) { | ||
auto err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, handler, this); | ||
ESP_ERROR_CHECK(err); | ||
} else { | ||
esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, handler); | ||
} | ||
} | ||
|
||
void EmbeddedEthernet::enableGotIpCallback(bool enable) | ||
{ | ||
auto handler = [](void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { | ||
auto ethernet = static_cast<EmbeddedEthernet*>(arg); | ||
if(!ethernet->gotIpCallback) { | ||
return; | ||
} | ||
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data; | ||
auto& ip_info = event->ip_info; | ||
ethernet->gotIpCallback(ip_info.ip.addr, ip_info.netmask.addr, ip_info.gw.addr); | ||
}; | ||
|
||
if(enable) { | ||
auto err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, handler, this); | ||
ESP_ERROR_CHECK(err); | ||
} else { | ||
esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, handler); | ||
} | ||
} | ||
|
||
MacAddress EmbeddedEthernet::getMacAddress() const | ||
{ | ||
MacAddress addr; | ||
if(mac != nullptr) { | ||
mac->get_addr(mac, &addr[0]); | ||
} | ||
return addr; | ||
} | ||
|
||
bool EmbeddedEthernet::setMacAddress(const MacAddress& addr) | ||
{ | ||
if(mac == nullptr) { | ||
return false; | ||
} | ||
return mac->set_addr(mac, &const_cast<MacAddress&>(addr)[0]) == ESP_OK; | ||
} | ||
|
||
bool EmbeddedEthernet::setSpeed(Speed speed) | ||
{ | ||
if(mac == nullptr) { | ||
return false; | ||
} | ||
return mac->set_speed(mac, eth_speed_t(speed)) == ESP_OK; | ||
} | ||
|
||
bool EmbeddedEthernet::setFullDuplex(bool enable) | ||
{ | ||
if(mac == nullptr) { | ||
return false; | ||
} | ||
return mac->set_duplex(mac, enable ? ETH_DUPLEX_FULL : ETH_DUPLEX_HALF) == ESP_OK; | ||
} | ||
|
||
bool EmbeddedEthernet::setLinkState(bool up) | ||
{ | ||
if(mac == nullptr) { | ||
return false; | ||
} | ||
return mac->set_link(mac, up ? ETH_LINK_UP : ETH_LINK_DOWN) == ESP_OK; | ||
} | ||
|
||
bool EmbeddedEthernet::setPromiscuous(bool enable) | ||
{ | ||
if(mac == nullptr) { | ||
return false; | ||
} | ||
return mac->set_promiscuous(mac, enable) == ESP_OK; | ||
} | ||
|
||
void EmbeddedEthernet::setHostname(const String& hostname) | ||
{ | ||
ESP_ERROR_CHECK(esp_netif_set_hostname(netif, hostname.c_str())); | ||
} | ||
|
||
String EmbeddedEthernet::getHostname() const | ||
{ | ||
const char* hostName; | ||
ESP_ERROR_CHECK(esp_netif_get_hostname(netif, &hostName)); | ||
return hostName; | ||
} | ||
|
||
IpAddress EmbeddedEthernet::getIP() const | ||
{ | ||
IpAddress addr; | ||
esp_netif_ip_info_t info; | ||
if(esp_netif_get_ip_info(netif, &info) == ESP_OK) { | ||
addr = info.ip.addr; | ||
} | ||
return addr; | ||
} | ||
|
||
extern "C" esp_err_t esp_netif_up(esp_netif_t* esp_netif); | ||
|
||
bool EmbeddedEthernet::setIP(IpAddress address, IpAddress netmask, IpAddress gateway) | ||
{ | ||
if(!enableDHCP(false)) { | ||
return false; | ||
} | ||
esp_netif_ip_info_t ipinfo{address, netmask, gateway}; | ||
if(esp_netif_set_ip_info(netif, &ipinfo) == ESP_OK) { | ||
debug_i("Ethernet IP successfully updated"); | ||
esp_netif_up(netif); | ||
} else { | ||
debug_e("Ethernet IP can't be updated"); | ||
enableDHCP(true); | ||
} | ||
return true; | ||
} | ||
|
||
bool EmbeddedEthernet::isEnabledDHCP() const | ||
{ | ||
esp_netif_dhcp_status_t status; | ||
if(esp_netif_dhcps_get_status(netif, &status) != ESP_OK) { | ||
return false; | ||
} | ||
|
||
return status == ESP_NETIF_DHCP_STARTED; | ||
} | ||
|
||
bool EmbeddedEthernet::enableDHCP(bool enable) | ||
{ | ||
if(enable) { | ||
return esp_netif_dhcpc_start(netif) == ESP_OK; | ||
} else { | ||
return esp_netif_dhcpc_stop(netif) == ESP_OK; | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
Sming/Components/Network/Arch/Esp32/Platform/EthernetPhy.cpp
This file contains 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,64 @@ | ||
/**** | ||
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. | ||
* Created 2015 by Skurydin Alexey | ||
* http://github.com/SmingHub/Sming | ||
* All files of the Sming Core are provided under the LGPL v3 license. | ||
* | ||
* EthernetPhy.cpp | ||
* | ||
* Class implementations for all supported ESP32 Ethernet PHY devices | ||
* | ||
****/ | ||
|
||
#include <Platform/Ethernet.h> | ||
#include <Network/Ethernet/Rtl8201.h> | ||
#include <Network/Ethernet/Ip101.h> | ||
#include <Network/Ethernet/Lan8720.h> | ||
#include <Network/Ethernet/Dp83848.h> | ||
#include <Network/Ethernet/Ksz8041.h> | ||
#include <esp_eth_phy.h> | ||
|
||
#define PHY_IMPL(class_name, func_name) \ | ||
Ethernet::PhyInstance* class_name::create(const PhyConfig& config) \ | ||
{ \ | ||
auto phy_config = get_esp_config(config); \ | ||
auto phy = esp_eth_phy_new_##func_name(&phy_config); \ | ||
return reinterpret_cast<PhyInstance*>(phy); \ | ||
} \ | ||
\ | ||
void class_name::destroy(PhyInstance* inst) \ | ||
{ \ | ||
esp_phy_destroy(inst); \ | ||
} | ||
|
||
namespace | ||
{ | ||
eth_phy_config_t get_esp_config(const Ethernet::PhyConfig& config) | ||
{ | ||
return eth_phy_config_t{ | ||
.phy_addr = config.phyAddr, | ||
.reset_timeout_ms = config.resetTimeout, | ||
.autonego_timeout_ms = config.autoNegTimeout, | ||
.reset_gpio_num = config.resetPin, | ||
}; | ||
} | ||
|
||
void esp_phy_destroy(Ethernet::PhyInstance* inst) | ||
{ | ||
auto phy = reinterpret_cast<esp_eth_phy_t*>(inst); | ||
if(phy != nullptr) { | ||
phy->del(phy); | ||
} | ||
} | ||
|
||
} // namespace | ||
|
||
namespace Ethernet | ||
{ | ||
PHY_IMPL(Ip101, ip101) | ||
PHY_IMPL(Rtl8201, rtl8201) | ||
PHY_IMPL(Lan8720, lan8720) | ||
PHY_IMPL(Dp83848, dp83848) | ||
PHY_IMPL(Ksz8041, ksz8041) | ||
|
||
} // namespace Ethernet |
Oops, something went wrong.