diff --git a/Sming/Arch/Esp32/Components/esp32/component.mk b/Sming/Arch/Esp32/Components/esp32/component.mk index 7ee639dc2c..d973b6461c 100644 --- a/Sming/Arch/Esp32/Components/esp32/component.mk +++ b/Sming/Arch/Esp32/Components/esp32/component.mk @@ -25,6 +25,7 @@ SDK_LIBDIRS := \ LIBDIRS += \ $(SDK_COMPONENT_LIBDIR) \ + $(SDK_BUILD_BASE)/esp-idf/mbedtls/mbedtls/library \ $(SDK_BUILD_BASE)/esp-idf/$(ESP_VARIANT) \ $(SDK_BUILD_BASE)/esp-idf/$(ESP_VARIANT)/ld \ $(COMPONENT_PATH)/ld \ @@ -145,6 +146,7 @@ SDK_COMPONENTS := \ esp-tls \ $(ESP_VARIANT) \ esp_common \ + esp_eth \ esp_event \ esp_gdbstub \ esp_hw_support \ @@ -195,7 +197,6 @@ SDK_COMPONENTS += \ bt \ coap \ console \ - esp_eth \ esp_http_client \ esp_http_server \ esp_https_ota \ @@ -331,12 +332,14 @@ export SDK_BUILD_BASE export SDK_COMPONENT_LIBDIR export SDK_COMPONENTS -$(SDK_BUILD_COMPLETE): $(SDKCONFIG_H) $(SDK_COMPONENT_LIBS) +$(SDK_BUILD_COMPLETE): $(SDKCONFIG_H) $(SDKCONFIG_MAKEFILE) + $(Q) $(SDK_BUILD) bootloader app + $(Q) $(MAKE) --no-print-directory -C $(SDK_DEFAULT_PATH) -f misc.mk copylibs touch $(SDK_BUILD_COMPLETE) $(SDKCONFIG_H) $(SDKCONFIG_MAKEFILE) $(SDK_COMPONENT_LIBS): $(SDK_CONFIG_DEFAULTS) | $(SDK_BUILD_BASE) $(SDK_COMPONENT_LIBDIR) - $(Q) $(SDK_BUILD) bootloader app - $(Q) $(MAKE) --no-print-directory -C $(SDK_DEFAULT_PATH) -f misc.mk copylibs + +$(SDK_COMPONENT_LIBS): $(SDK_BUILD_COMPLETE) $(SDK_CONFIG_DEFAULTS): $(Q) cp $@.$(BUILD_TYPE) $@ @@ -348,7 +351,7 @@ sdk-menuconfig: $(SDK_CONFIG_DEFAULTS) | $(SDK_BUILD_BASE) ##Configure SDK optio @echo Now run 'make esp32-build' .PHONY: sdk-defconfig -sdk-defconfig: $(SDK_BUILD_BASE)/include/sdkconfig.h ##Create default SDK config files +sdk-defconfig: $(SDKCONFIG_H) ##Create default SDK config files .PHONY: sdk-menuconfig-clean sdk-menuconfig-clean: esp32-clean ##Wipe SDK configuration and revert to defaults diff --git a/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.debug b/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.debug index 4f07843fa8..c7e8dc3728 100644 --- a/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.debug +++ b/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.debug @@ -13,6 +13,13 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y # Mandatory LWIP changes CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=8192 +# Ethernet +#CONFIG_ETH_USE_ESP32_EMAC=y +#CONFIG_ETH_PHY_INTERFACE_RMII=y +#CONFIG_ETH_RMII_CLK_INPUT=y +#CONFIG_ETH_RMII_CLK_IN_GPIO=0 +CONFIG_ETH_USE_SPI_ETHERNET=n + # Mandatory Sming framework changes CONFIG_ESP_TIMER_TASK_STACK_SIZE=16384 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=8192 diff --git a/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.release b/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.release index 400963c451..14b10b5611 100644 --- a/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.release +++ b/Sming/Arch/Esp32/Components/esp32/project.esp32/sdkconfig.defaults.release @@ -13,6 +13,13 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y # Mandatory LWIP changes CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=8192 +# Ethernet +#CONFIG_ETH_USE_ESP32_EMAC=y +#CONFIG_ETH_PHY_INTERFACE_RMII=y +#CONFIG_ETH_RMII_CLK_INPUT=y +#CONFIG_ETH_RMII_CLK_IN_GPIO=0 +CONFIG_ETH_USE_SPI_ETHERNET=n + # Mandatory Sming framework changes CONFIG_ESP_TIMER_TASK_STACK_SIZE=16384 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=8192 diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/misc.mk b/Sming/Arch/Esp32/Components/esp32/sdk/misc.mk index 0793f55563..e117fafdeb 100644 --- a/Sming/Arch/Esp32/Components/esp32/sdk/misc.mk +++ b/Sming/Arch/Esp32/Components/esp32/sdk/misc.mk @@ -7,7 +7,7 @@ include $(SMING_HOME)/build.mk all: # List of all generated SDK libraries -SDK_ARCHIVE_DIRS = $(foreach c,$(SDK_COMPONENTS),$(SDK_BUILD_BASE)/esp-idf/$c $(call ListAllSubDirs,$(SDK_BUILD_BASE)/esp-idf/$c)) +SDK_ARCHIVE_DIRS = $(foreach c,$(SDK_COMPONENTS),$(SDK_BUILD_BASE)/esp-idf/$c) SDK_ARCHIVE_LIST = $(sort $(foreach d,$(SDK_ARCHIVE_DIRS),$(wildcard $d/*.a))) # diff --git a/Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp b/Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp new file mode 100644 index 0000000000..826dfd9296 --- /dev/null +++ b/Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp @@ -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 +// #include +#include +#include +#include + +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(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(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(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(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(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; + } +} diff --git a/Sming/Components/Network/Arch/Esp32/Platform/EthernetPhy.cpp b/Sming/Components/Network/Arch/Esp32/Platform/EthernetPhy.cpp new file mode 100644 index 0000000000..339330a7ac --- /dev/null +++ b/Sming/Components/Network/Arch/Esp32/Platform/EthernetPhy.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +#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(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(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 diff --git a/Sming/Components/Network/Arch/Esp32/Platform/include/Platform/EmbeddedEthernet.h b/Sming/Components/Network/Arch/Esp32/Platform/include/Platform/EmbeddedEthernet.h new file mode 100644 index 0000000000..8b11f3e64e --- /dev/null +++ b/Sming/Components/Network/Arch/Esp32/Platform/include/Platform/EmbeddedEthernet.h @@ -0,0 +1,82 @@ +/**** + * 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.h + * + ****/ + +#pragma once + +#include + +struct esp_eth_mac_s; +struct esp_eth_phy_s; +struct esp_netif_obj; + +/** + * @brief Ethernet provider using ESP32 embedded MAC. Requires an external PHY. + * + * See https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/network/esp_eth.html. + * + * These are the reduced (RMII) PHY connections. + * Note that the high-speed signals may not be re-allocated. + * + * Signal GPIO Direction + * ------ ---- --------- + * TXD0 19 OUT + * TXD1 22 OUT + * TX_EN 21 OUT + * RXD0 25 IN + * RXD1 26 IN + * CRS_DV 27 IN + * Receive Data Valid + * MDC 23 OUT: configurable + * MDIO 18 OUT: configurable + * CLK_MII 0 IN: No other pins supported + * OUT: alternate pins: 16, 17 + * 50MHz clock provided either by the PHY or the MAC. Default is PHY. + * + * Note: Configuring clock options must be done via SDK (make sdk-menuconfig). + * ESP-IDF v4.4 will add the ability to override these in software. + * + * The following connections are optional: + * + * PHY_RESET - OUT (set via PhyConfig) + */ +class EmbeddedEthernet : public Ethernet::Service +{ +public: + EmbeddedEthernet(Ethernet::PhyFactory& phyFactory) : phyFactory(phyFactory) + { + } + + bool begin(const Ethernet::Config& config) override; + void end() override; + MacAddress getMacAddress() const override; + bool setMacAddress(const MacAddress& addr) override; + bool setSpeed(Ethernet::Speed speed) override; + bool setFullDuplex(bool enable) override; + bool setLinkState(bool up) override; + bool setPromiscuous(bool enable) override; + void setHostname(const String& hostname) override; + String getHostname() const override; + IpAddress getIP() const override; + bool setIP(IpAddress address, IpAddress netmask, IpAddress gateway) override; + bool isEnabledDHCP() const override; + bool enableDHCP(bool enable) override; + +private: + void enableEventCallback(bool enable); + void enableGotIpCallback(bool enable); + + Ethernet::PhyFactory& phyFactory; + void* handle{nullptr}; + esp_netif_obj* netif{nullptr}; + void* netif_glue{nullptr}; + esp_eth_mac_s* mac{nullptr}; + esp_eth_phy_s* phy{nullptr}; + Ethernet::Event state{Ethernet::Event::Disconnected}; +}; diff --git a/Sming/Components/Network/component.mk b/Sming/Components/Network/component.mk index 572ef6a501..268da4aca1 100644 --- a/Sming/Components/Network/component.mk +++ b/Sming/Components/Network/component.mk @@ -3,7 +3,9 @@ COMPONENT_SRCDIRS := \ $(call ListAllSubDirs,$(COMPONENT_PATH)/src) \ $(call ListAllSubDirs,$(COMPONENT_PATH)/Arch/$(SMING_ARCH)) -COMPONENT_INCDIRS := src +COMPONENT_INCDIRS := \ + src \ + Arch/$(SMING_ARCH)/Platform/include COMPONENT_DOXYGEN_INPUT := src diff --git a/Sming/Components/Network/src/Network/Ethernet/Dp83848.h b/Sming/Components/Network/src/Network/Ethernet/Dp83848.h new file mode 100644 index 0000000000..e79381c987 --- /dev/null +++ b/Sming/Components/Network/src/Network/Ethernet/Dp83848.h @@ -0,0 +1,29 @@ +/**** + * 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. + * + * Dp83848.h + * + ****/ + +#pragma once + +#include + +namespace Ethernet +{ +/** + * @brief DP 83848 PHY interface + */ +class Dp83848 : public PhyFactory +{ +public: + using PhyFactory::PhyFactory; + + PhyInstance* create(const PhyConfig& config) override; + void destroy(PhyInstance* inst) override; +}; + +} // namespace Ethernet diff --git a/Sming/Components/Network/src/Network/Ethernet/Ip101.h b/Sming/Components/Network/src/Network/Ethernet/Ip101.h new file mode 100644 index 0000000000..a2caf1c1e2 --- /dev/null +++ b/Sming/Components/Network/src/Network/Ethernet/Ip101.h @@ -0,0 +1,29 @@ +/**** + * 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. + * + * Ip101.h + * + ****/ + +#pragma once + +#include + +namespace Ethernet +{ +/** + * @brief IP101 PHY interface + */ +class Ip101 : public PhyFactory +{ +public: + using PhyFactory::PhyFactory; + + PhyInstance* create(const PhyConfig& config) override; + void destroy(PhyInstance* inst) override; +}; + +} // namespace Ethernet diff --git a/Sming/Components/Network/src/Network/Ethernet/Ksz8041.h b/Sming/Components/Network/src/Network/Ethernet/Ksz8041.h new file mode 100644 index 0000000000..6ce64b5795 --- /dev/null +++ b/Sming/Components/Network/src/Network/Ethernet/Ksz8041.h @@ -0,0 +1,29 @@ +/**** + * 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. + * + * Ksz8041.h + * + ****/ + +#pragma once + +#include + +namespace Ethernet +{ +/** + * @brief KSZ 8041 PHY interface + */ +class Ksz8041 : public PhyFactory +{ +public: + using PhyFactory::PhyFactory; + + PhyInstance* create(const PhyConfig& config) override; + void destroy(PhyInstance* inst) override; +}; + +} // namespace Ethernet diff --git a/Sming/Components/Network/src/Network/Ethernet/Lan8720.h b/Sming/Components/Network/src/Network/Ethernet/Lan8720.h new file mode 100644 index 0000000000..6b49452ef8 --- /dev/null +++ b/Sming/Components/Network/src/Network/Ethernet/Lan8720.h @@ -0,0 +1,29 @@ +/**** + * 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. + * + * Lan8720.h + * + ****/ + +#pragma once + +#include + +namespace Ethernet +{ +/** + * @brief LAN 8720 PHY interface + */ +class Lan8720 : public PhyFactory +{ +public: + using PhyFactory::PhyFactory; + + PhyInstance* create(const PhyConfig& config) override; + void destroy(PhyInstance* inst) override; +}; + +} // namespace Ethernet diff --git a/Sming/Components/Network/src/Network/Ethernet/Rtl8201.h b/Sming/Components/Network/src/Network/Ethernet/Rtl8201.h new file mode 100644 index 0000000000..748f3f3306 --- /dev/null +++ b/Sming/Components/Network/src/Network/Ethernet/Rtl8201.h @@ -0,0 +1,29 @@ +/**** + * 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. + * + * Rtl8201.h + * + ****/ + +#pragma once + +#include + +namespace Ethernet +{ +/** + * @brief RTL 8201 PHY interface + */ +class Rtl8201 : public PhyFactory +{ +public: + using PhyFactory::PhyFactory; + + PhyInstance* create(const PhyConfig& config) override; + void destroy(PhyInstance* inst) override; +}; + +} // namespace Ethernet diff --git a/Sming/Components/Network/src/Platform/Ethernet.cpp b/Sming/Components/Network/src/Platform/Ethernet.cpp new file mode 100644 index 0000000000..d211484170 --- /dev/null +++ b/Sming/Components/Network/src/Platform/Ethernet.cpp @@ -0,0 +1,37 @@ +/**** + * 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. + * + * Ethernet.cpp + * + ****/ + +#include "Ethernet.h" + +String toString(Ethernet::Event event) +{ + switch(event) { +#define XX(tag, desc) \ + case Ethernet::Event::tag: \ + return F(#tag); + ETHERNET_EVENT_MAP(XX) +#undef XX + default: + return F("Unknown_") + unsigned(event); + } +} + +String toLongString(Ethernet::Event event) +{ + switch(event) { +#define XX(tag, desc) \ + case Ethernet::Event::tag: \ + return F(desc); + ETHERNET_EVENT_MAP(XX) +#undef XX + default: + return F("Unknown_") + unsigned(event); + } +} diff --git a/Sming/Components/Network/src/Platform/Ethernet.h b/Sming/Components/Network/src/Platform/Ethernet.h new file mode 100644 index 0000000000..f3662ed01a --- /dev/null +++ b/Sming/Components/Network/src/Platform/Ethernet.h @@ -0,0 +1,244 @@ +/**** + * 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. + * + * Ethernet.h + * + ****/ + +#pragma once + +#include +#include +#include +#include +#include + +/** + * @brief Ethernet event code map + * @note These codes are based on the ESP IDF public API. + */ +#define ETHERNET_EVENT_MAP(XX) \ + XX(Start, "Ethernet driver Started") \ + XX(Stop, "Ethernet driver stopped") \ + XX(Connected, "Ethernet link established") \ + XX(Disconnected, "Ethernet link lost") + +namespace Ethernet +{ +/** + * @brief Ethernet event codes + */ +enum class Event { +#define XX(tag, desc) tag, + ETHERNET_EVENT_MAP(XX) +#undef XX +}; + +/** + * @brief Delegate type for Ethernet events + * @param event Which event occurred + * @param mac Provided on 'Connected' event only + */ +using EventDelegate = Delegate; + +/** + * @brief Delegate type for 'got IP address' event + */ +using GotIpDelegate = Delegate; + +/** + * @brief Use default pin for platform + */ +constexpr int8_t PIN_DEFAULT{-2}; + +/** + * @brief Do not configure this pin + * + * Only applies if pin is optional, otherwise it will be interpreted as 'auto detect'. + */ +constexpr int8_t PIN_UNUSED{-1}; + +/** + * @brief Configuration for Ethernet MAC + */ +struct MacConfig { + int8_t smiMdcPin = PIN_DEFAULT; //< SMI MDC GPIO number + int8_t smiMdioPin = PIN_DEFAULT; //< SMI MDIO GPIO number +}; + +/** + * @brief Link speed + */ +enum class Speed { + MBPS10, + MBPS100, +}; + +/** + * @brief Constructed PHY instance. An opaque, implementation-specific type. + */ +struct PhyInstance; + +/** + * @brief Automatically detect PHY address during initialization + */ +constexpr int8_t PHY_ADDR_AUTO{-1}; + +/** + * @brief PHY configuration + */ +struct PhyConfig { + int8_t phyAddr = PHY_ADDR_AUTO; ///< PHY address + int8_t resetPin = PIN_UNUSED; ///< Reset GPIO number */ + uint16_t resetTimeout = 100; ///< Reset timeout value in milliseconds + uint16_t autoNegTimeout = 4000; ///< Auto-negotiation timeout in milliseconds +}; + +/** + * @brief Virtual class used to construct a specific PHY instance + * + * Applications provide an instance of this factory class so that the Service + * can create and configure it at the correct point in initialisation or teardown. + */ +class PhyFactory +{ +public: + using PhyInstance = Ethernet::PhyInstance; + + /** + * @brief Called by the Service to construct a PHY instance. + */ + virtual PhyInstance* create(const PhyConfig& config) = 0; + + /** + * @brief Called by the Service to destroy a PHY instance. + */ + virtual void destroy(PhyInstance* inst) = 0; +}; + +/** + * @brief Service configuration options + */ +struct Config { + MacConfig mac; + PhyConfig phy; +}; + +/** + * @brief Abstract Service class + * + * Provides a common implementation for TCP/IP ethernet support. + * + * An Ethernet interface requires a MAC layer plus PHY. + * + * The ESP32, for example, contains a MAC but requires an external PHY. + * Other solutions, such as the W5500, contain MAC+PHY and require the correct + * PhyFactory to work. + * + * Ethernet implementations should provide appropriate setup methods which are called by the application + * before invoking `begin()`. + */ +class Service +{ +public: + /** + * @brief Configure and start the ethernet service + * @param config Configuration options + * + * Applications should expect to receive Start and Connected events following this call. + */ + virtual bool begin(const Config& config) = 0; + + /** + * @brief Tear down the ethernet connection + */ + virtual void end() = 0; + + /** + * @brief Get MAC address + */ + virtual MacAddress getMacAddress() const = 0; + + /** + * @brief Set MAC address + */ + virtual bool setMacAddress(const MacAddress& addr) = 0; + + /** + * @brief Set speed of MAC + */ + virtual bool setSpeed(Speed speed) = 0; + + /** + * @brief Set duplex mode of MAC + */ + virtual bool setFullDuplex(bool enable) = 0; + + /** + * @brief Set link status of MAC + */ + virtual bool setLinkState(bool up) = 0; + + /** + * @brief Set MAC promiscuous mode + */ + virtual bool setPromiscuous(bool enable) = 0; + + /** + * @brief Set DHCP hostname + */ + virtual void setHostname(const String& hostname) = 0; + + /** + * @brief Get DHCP hostname + */ + virtual String getHostname() const = 0; + + /** + * @brief Get current IP address + */ + virtual IpAddress getIP() const = 0; + + /** + * @brief Set static IP address + */ + virtual bool setIP(IpAddress address, IpAddress netmask, IpAddress gateway) = 0; + + /** + * @brief Determine if DHCP is active for this interface + */ + virtual bool isEnabledDHCP() const = 0; + + /** + * @brief Enable/disable DHCP on this interface + */ + virtual bool enableDHCP(bool enable) = 0; + + /** + * @brief Set callback for ethernet events + */ + void onEvent(EventDelegate callback) + { + eventCallback = callback; + } + + /** + * @brief Set callback for 'station connected with IP address' event + */ + void onGotIp(GotIpDelegate callback) + { + gotIpCallback = callback; + } + +protected: + EventDelegate eventCallback; + GotIpDelegate gotIpCallback; +}; + +} // namespace Ethernet + +String toString(Ethernet::Event event); +String toLongString(Ethernet::Event event); diff --git a/docs/source/framework/platform/ethernet.rst b/docs/source/framework/platform/ethernet.rst new file mode 100644 index 0000000000..74bcde4b3e --- /dev/null +++ b/docs/source/framework/platform/ethernet.rst @@ -0,0 +1,7 @@ +Ethernet +======== + +Currently only supported on ESP32 using embedded MAC. + +.. doxygennamespace:: Ethernet + :members: diff --git a/docs/source/framework/platform/index.rst b/docs/source/framework/platform/index.rst index a96ba829b7..29ad6f21b3 100644 --- a/docs/source/framework/platform/index.rst +++ b/docs/source/framework/platform/index.rst @@ -2,7 +2,7 @@ Platform Support ================ .. toctree:: + :glob: :maxdepth: 1 - wifi - system + * diff --git a/samples/Basic_Ethernet/.cproject b/samples/Basic_Ethernet/.cproject new file mode 100644 index 0000000000..335030239d --- /dev/null +++ b/samples/Basic_Ethernet/.cproject @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + -f ${ProjDirPath}/Makefile + all + true + true + true + + + make + -f ${ProjDirPath}/Makefile + clean + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flash + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashonefile + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashinit + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashboot + true + true + true + + + make + -f ${ProjDirPath}/Makefile + rebuild + true + true + true + + + + + + + + + + + + + + + + + + + + diff --git a/samples/Basic_Ethernet/.project b/samples/Basic_Ethernet/.project new file mode 100644 index 0000000000..ded68cb818 --- /dev/null +++ b/samples/Basic_Ethernet/.project @@ -0,0 +1,28 @@ + + + Basic_Ethernet + + + SmingFramework + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/samples/Basic_Ethernet/Makefile b/samples/Basic_Ethernet/Makefile new file mode 100644 index 0000000000..ff51b6c3a7 --- /dev/null +++ b/samples/Basic_Ethernet/Makefile @@ -0,0 +1,9 @@ +##################################################################### +#### Please don't change this file. Use component.mk instead #### +##################################################################### + +ifndef SMING_HOME +$(error SMING_HOME is not set: please configure it as an environment variable) +endif + +include $(SMING_HOME)/project.mk diff --git a/samples/Basic_Ethernet/README.rst b/samples/Basic_Ethernet/README.rst new file mode 100644 index 0000000000..798fef75c9 --- /dev/null +++ b/samples/Basic_Ethernet/README.rst @@ -0,0 +1,16 @@ +Basic Ethernet +============== + +Demonstrates creating an ethernet connection. + +Currently only supported for ESP32 with internal MAC. +An external PHY is required. This demonstration uses a commonly available LAN8270 module. + +.. note: + + The MAC/PHY interface uses high-speed signalling so connections must be solid. + The connection may *appear* to work but fail, for example, to obtain network address. + If this happens, check connections. + + In the current configuration a 50MHz synchronisation clock is received from the PHY on GPIO0. + Not all ESP32 development boards have this pin available! diff --git a/samples/Basic_Ethernet/app/application.cpp b/samples/Basic_Ethernet/app/application.cpp new file mode 100644 index 0000000000..858b9abb1f --- /dev/null +++ b/samples/Basic_Ethernet/app/application.cpp @@ -0,0 +1,53 @@ +#include + +#ifdef SUBARCH_ESP32 + +#include +#include + +Ethernet::Lan8720 phy; +EmbeddedEthernet ethernet(phy); + +static void ethernetEventHandler(Ethernet::Event event) +{ + Serial.print(toString(event)); + Serial.print(_F(", MAC = ")); + Serial.println(ethernet.getMacAddress().toString()); +} + +static void ethernetGotIp(IpAddress ip, IpAddress netmask, IpAddress gateway) +{ + Serial.print(_F("Connected! Ethernet IP ")); + Serial.print(ip.toString()); + Serial.print(_F(", netmask ")); + Serial.print(netmask.toString()); + Serial.print(_F(", gateway ")); + Serial.println(gateway.toString()); +} + +void init() +{ + Serial.begin(SERIAL_BAUD_RATE); + Serial.systemDebugOutput(true); // Allow debug print to serial + + ethernet.onEvent(ethernetEventHandler); + ethernet.onGotIp(ethernetGotIp); + + // Modify default config as required + Ethernet::Config config; + ethernet.begin(config); + + // Change the advertised hostname for DHCP + ethernet.setHostname("sming-ethernet"); + + // Set a static IP + // ethernet.setIP(IpAddress("192.168.1.12"), IpAddress("255.255.255.0"), IpAddress("192.168.1.254")); +} + +#else + +void init() +{ +} + +#endif