From 4e03ea49f451c7626c0e1ac2271d4774bd24d471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sch=C3=A4fer?= Date: Sat, 20 Jan 2024 17:21:49 +0100 Subject: [PATCH 1/6] [SSC] Bump to mRos2 0.5.4 --- mros2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mros2 b/mros2 index 7264c5f..b3a7118 160000 --- a/mros2 +++ b/mros2 @@ -1 +1 @@ -Subproject commit 7264c5ff5f855263c84cd6777527d623269b1583 +Subproject commit b3a711811409c980af2f4f38127fbeae54411cfb From 39d823dc9e99e99c1407a08481a5ce7fa91f7c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sch=C3=A4fer?= Date: Sat, 20 Jan 2024 17:42:12 +0100 Subject: [PATCH 2/6] [SSC] Make python call compatable with esp-idf virtual environment. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae69007..ad958c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ idf_component_register( ## that contain application code files add_custom_command( OUTPUT templates.hpp - COMMAND python3 ${COMPONENT_PATH}/mros2/mros2_header_generator/templates_generator.py --outdir ${COMPONENT_PATH}/platform --indir ${CMAKE_SOURCE_DIR}/main) + COMMAND python ${COMPONENT_PATH}/mros2/mros2_header_generator/templates_generator.py --outdir ${COMPONENT_PATH}/platform --indir ${CMAKE_SOURCE_DIR}/main) add_custom_target(Template SOURCES templates.hpp) add_dependencies(${COMPONENT_LIB} Template) From 15547958d5eaf0ccf58d0df00590f8e0b04f8471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sch=C3=A4fer?= Date: Sat, 20 Jan 2024 18:05:30 +0100 Subject: [PATCH 3/6] [SSC] Add ethernet support. --- CMakeLists.txt | 4 +- Kconfig.projbuild | 204 +++++++++++++++++++++ platform/ethernet/ethernet.c | 338 +++++++++++++++++++++++++++++++++++ platform/ethernet/ethernet.h | 38 ++++ platform/mros2-platform.cpp | 2 +- platform/mros2-platform.h | 1 + platform/wifi/wifi.c | 8 +- platform/wifi/wifi.h | 13 +- 8 files changed, 600 insertions(+), 8 deletions(-) create mode 100644 Kconfig.projbuild create mode 100644 platform/ethernet/ethernet.c create mode 100644 platform/ethernet/ethernet.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ad958c1..788e584 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(SRCS "mros2/src/mros2.cpp" "cmsis-esp32/lwip.c" "cmsis-esp32/cmsis-esp.c" "platform/wifi/wifi.c" + "platform/ethernet/ethernet.c" "platform/mros2-platform.cpp" ) @@ -32,6 +33,7 @@ set(INCS "mros2/include" "cmsis-esp32/include" "platform" "platform/wifi" + "platform/ethernet" ${CMAKE_SOURCE_DIR}/main ) @@ -42,7 +44,7 @@ endif() idf_component_register( SRCS ${SRCS} INCLUDE_DIRS ${INCS} - REQUIRES nvs_flash esp_wifi) + REQUIRES nvs_flash esp_wifi esp_eth) # Generate plaform/templates.hpp from mros2 application code ## You can add dir(s) in `--indir` if you have several dirs diff --git a/Kconfig.projbuild b/Kconfig.projbuild new file mode 100644 index 0000000..4c06f84 --- /dev/null +++ b/Kconfig.projbuild @@ -0,0 +1,204 @@ +menu "mROS Settings" + + ################################## + # CHOOSE NETWORK INTERFACE # + ################################## + + choice + prompt "mROS network interface select" + config M_ROS_ESP_NETIF_WLAN + bool "WLAN interface" + config M_ROS_ESP_NETIF_ENET + bool "Ethernet interface" + endchoice + + + ##################### + # WLAN CONFIG # + ##################### + + if M_ROS_ESP_NETIF_WLAN + + menu "WiFi Configuration" + + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + + config ESP_MAXIMUM_RETRY + int "Maximum retry" + default 5 + help + Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. + endmenu + + endif # M_ROS_ESP_NETIF_WLAN + + ######################### + # ETHERNET CONFIG # + ######################### + + if M_ROS_ESP_NETIF_ENET + + menu "Ethernet Configuration" + config M_ROS_USE_SPI_ETHERNET + bool + + choice M_ROS_ETHERNET_TYPE + prompt "Ethernet Type" + default M_ROS_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32 + default M_ROS_USE_W5500 + help + Select which kind of Ethernet will be used in the example. + + config M_ROS_USE_INTERNAL_ETHERNET + depends on IDF_TARGET_ESP32 + select ETH_USE_ESP32_EMAC + bool "Internal EMAC" + help + Select internal Ethernet MAC controller. + + config M_ROS_USE_DM9051 + bool "DM9051 Module" + select M_ROS_USE_SPI_ETHERNET + select ETH_USE_SPI_ETHERNET + select ETH_SPI_ETHERNET_DM9051 + help + Select external SPI-Ethernet module (DM9051). + + config M_ROS_USE_W5500 + bool "W5500 Module" + select M_ROS_USE_SPI_ETHERNET + select ETH_USE_SPI_ETHERNET + select ETH_SPI_ETHERNET_W5500 + help + Select external SPI-Ethernet module (W5500). + endchoice # M_ROS_ETHERNET_TYPE + + if M_ROS_USE_INTERNAL_ETHERNET + choice M_ROS_ETH_PHY_MODEL + prompt "Ethernet PHY Device" + default M_ROS_ETH_PHY_IP101 + help + Select the Ethernet PHY device to use in the example. + + config M_ROS_ETH_PHY_IP101 + bool "IP101" + help + IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver. + Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it. + + config M_ROS_ETH_PHY_RTL8201 + bool "RTL8201/SR8201" + help + RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX. + Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it. + + config M_ROS_ETH_PHY_LAN8720 + bool "LAN8720" + help + LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support. + Goto https://www.microchip.com/LAN8720A for more information about it. + + config M_ROS_ETH_PHY_DP83848 + bool "DP83848" + help + DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver. + Goto http://www.ti.com/product/DP83848J for more information about it. + + config M_ROS_ETH_PHY_KSZ8041 + bool "KSZ8041" + help + The KSZ8041 is a single supply 10Base-T/100Base-TX Physical Layer Transceiver. + Goto https://www.microchip.com/wwwproducts/en/KSZ8041 for more information about it. + endchoice # M_ROS_ETH_PHY_MODEL + + config M_ROS_ETH_MDC_GPIO + int "SMI MDC GPIO number" + default 23 + help + Set the GPIO number used by SMI MDC. + + config M_ROS_ETH_MDIO_GPIO + int "SMI MDIO GPIO number" + default 18 + help + Set the GPIO number used by SMI MDIO. + endif # M_ROS_USE_INTERNAL_ETHERNET + + if M_ROS_USE_SPI_ETHERNET + config M_ROS_ETH_SPI_HOST + int "SPI Host Number" + range 0 2 + default 1 + help + Set the SPI host used to communicate with the SPI Ethernet Controller. + + config M_ROS_ETH_SPI_SCLK_GPIO + int "SPI SCLK GPIO number" + range 0 33 + default 20 + help + Set the GPIO number used by SPI SCLK. + + config M_ROS_ETH_SPI_MOSI_GPIO + int "SPI MOSI GPIO number" + range 0 33 + default 19 + help + Set the GPIO number used by SPI MOSI. + + config M_ROS_ETH_SPI_MISO_GPIO + int "SPI MISO GPIO number" + range 0 33 + default 18 + help + Set the GPIO number used by SPI MISO. + + config M_ROS_ETH_SPI_CS_GPIO + int "SPI CS GPIO number" + range 0 33 + default 21 + help + Set the GPIO number used by SPI CS. + + config M_ROS_ETH_SPI_CLOCK_MHZ + int "SPI clock speed (MHz)" + range 5 80 + default 36 + help + Set the clock speed (MHz) of SPI interface. + + config M_ROS_ETH_SPI_INT_GPIO + int "Interrupt GPIO number" + default 4 + help + Set the GPIO number used by the SPI Ethernet module interrupt line. + endif # M_ROS_USE_SPI_ETHERNET + + config M_ROS_ETH_PHY_RST_GPIO + int "PHY Reset GPIO number" + default 5 + help + Set the GPIO number used to reset PHY chip. + Set to -1 to disable PHY chip hardware reset. + + config M_ROS_ETH_PHY_ADDR + int "PHY Address" + range 0 31 + default 1 + help + Set PHY address according your board schematic. + endmenu + + endif # M_ROS_ESP_NETIF_ENET + + endmenu \ No newline at end of file diff --git a/platform/ethernet/ethernet.c b/platform/ethernet/ethernet.c new file mode 100644 index 0000000..e1b691f --- /dev/null +++ b/platform/ethernet/ethernet.c @@ -0,0 +1,338 @@ +/* Ethernet Basic Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "ethernet.h" + +#ifdef CONFIG_M_ROS_ESP_NETIF_ENET + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_netif.h" +#include "esp_eth.h" +#include "esp_event.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "sdkconfig.h" +#if CONFIG_M_ROS_USE_SPI_ETHERNET +#include "driver/spi_master.h" +#endif // CONFIG_ETH_USE_SPI_ETHERNET + +static EventGroupHandle_t s_ethernet_event_group; +static const char *TAG = "ethernet"; + +#if CONFIG_M_ROS_USE_SPI_ETHERNET +#define INIT_SPI_ETH_MODULE_CONFIG(eth_module_config, num) \ + do \ + { \ + eth_module_config[num].spi_cs_gpio = CONFIG_M_ROS_ETH_SPI_CS##num##_GPIO; \ + eth_module_config[num].int_gpio = CONFIG_M_ROS_ETH_SPI_INT##num##_GPIO; \ + eth_module_config[num].phy_reset_gpio = CONFIG_M_ROS_ETH_SPI_PHY_RST##num##_GPIO; \ + eth_module_config[num].phy_addr = CONFIG_M_ROS_ETH_SPI_PHY_ADDR##num; \ + } while (0) + +typedef struct +{ + uint8_t spi_cs_gpio; + uint8_t int_gpio; + int8_t phy_reset_gpio; + uint8_t phy_addr; +} spi_eth_module_config_t; +#endif + +/** Event handler for Ethernet events */ +static void eth_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + uint8_t mac_addr[6] = {0}; + /* we can get the ethernet driver handle from event data */ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + + switch (event_id) + { + case ETHERNET_EVENT_CONNECTED: + esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr); + ESP_LOGI(TAG, "Ethernet Link Up"); + ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + break; + case ETHERNET_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "Ethernet Link Down"); + xEventGroupSetBits(s_ethernet_event_group, ETHERNET_FAIL_BIT); + break; + case ETHERNET_EVENT_START: + ESP_LOGI(TAG, "Ethernet Started"); + break; + case ETHERNET_EVENT_STOP: + ESP_LOGI(TAG, "Ethernet Stopped"); + xEventGroupSetBits(s_ethernet_event_group, ETHERNET_FAIL_BIT); + break; + default: + break; + } +} + +/* keep IP address obtained in event_handler */ +static uint32_t mros2_ip_addr; +/** Event handler for IP_EVENT_ETH_GOT_IP */ +static void got_ip_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + const esp_netif_ip_info_t *ip_info = &event->ip_info; + + ESP_LOGI(TAG, "Ethernet Got IP Address"); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); + ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); + ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + /* keep IP address obtained in event_handler */ + mros2_ip_addr = event->ip_info.ip.addr; + xEventGroupSetBits(s_ethernet_event_group, ETHERNET_CONNECTED_BIT); +} + +#define PIN_PHY_POWER GPIO_NUM_12 +void init_network(void) +{ + s_ethernet_event_group = xEventGroupCreate(); + + // Initialize TCP/IP network interface (should be called only once in application) + ESP_ERROR_CHECK(esp_netif_init()); + // Create default event loop that running in background + ESP_ERROR_CHECK(esp_event_loop_create_default()); + +#if CONFIG_M_ROS_USE_INTERNAL_ETHERNET + + // Create new default instance of esp-netif for Ethernet + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); + esp_netif_t *eth_netif = esp_netif_new(&cfg); + + // Init MAC and PHY configs to default + eth_esp32_emac_config_t emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + eth_mac_config_t eth_mac_config = ETH_MAC_DEFAULT_CONFIG(); + eth_mac_config.sw_reset_timeout_ms = 250; // Needed for some ethernet controllers to initiate + + phy_config.phy_addr = CONFIG_M_ROS_ETH_PHY_ADDR; + phy_config.reset_gpio_num = CONFIG_M_ROS_ETH_PHY_RST_GPIO; + esp_rom_gpio_pad_select_gpio(PIN_PHY_POWER); + gpio_set_direction(PIN_PHY_POWER,GPIO_MODE_OUTPUT); + gpio_set_level(PIN_PHY_POWER, 1); + vTaskDelay(pdMS_TO_TICKS(10)); + emac_config.smi_mdc_gpio_num = 23; + emac_config.smi_mdio_gpio_num = 18; + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&emac_config, ð_mac_config); + +#if CONFIG_M_ROS_ETH_PHY_IP101 + esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); +#elif CONFIG_M_ROS_ETH_PHY_RTL8201 + esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config); +#elif CONFIG_M_ROS_ETH_PHY_LAN8720 + esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config); +#elif CONFIG_M_ROS_ETH_PHY_DP83848 + esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config); +#elif CONFIG_M_ROS_ETH_PHY_KSZ8041 + esp_eth_phy_t *phy = esp_eth_phy_new_ksz8041(&phy_config); +#elif CONFIG_M_ROS_ETH_PHY_KSZ8081 + esp_eth_phy_t *phy = esp_eth_phy_new_ksz8081(&phy_config); +#endif + + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); + esp_eth_handle_t eth_handle = NULL; + ESP_ERROR_CHECK(esp_eth_driver_install(&config, ð_handle)); + /* attach Ethernet driver to TCP/IP stack */ + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle))); +#endif // CONFIG_M_ROS_USE_INTERNAL_ETHERNET + +#if CONFIG_M_ROS_USE_SPI_ETHERNET + // Create instance(s) of esp-netif for SPI Ethernet(s) + esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); + esp_netif_config_t cfg_spi = { + .base = &esp_netif_config, + .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH}; + esp_netif_t *eth_netif_spi[CONFIG_M_ROS_SPI_ETHERNETS_NUM] = {NULL}; + char if_key_str[10]; + char if_desc_str[10]; + char num_str[3]; + for (int i = 0; i < CONFIG_M_ROS_SPI_ETHERNETS_NUM; i++) + { + itoa(i, num_str, 10); + strcat(strcpy(if_key_str, "ETH_SPI_"), num_str); + strcat(strcpy(if_desc_str, "eth"), num_str); + esp_netif_config.if_key = if_key_str; + esp_netif_config.if_desc = if_desc_str; + esp_netif_config.route_prio = 30 - i; + eth_netif_spi[i] = esp_netif_new(&cfg_spi); + } + + // Init MAC and PHY configs to default + eth_mac_config_t mac_config_spi = ETH_MAC_DEFAULT_CONFIG(); + eth_phy_config_t phy_config_spi = ETH_PHY_DEFAULT_CONFIG(); + + // Install GPIO ISR handler to be able to service SPI Eth modlues interrupts + gpio_install_isr_service(0); + + // Init SPI bus + spi_device_handle_t spi_handle[CONFIG_M_ROS_SPI_ETHERNETS_NUM] = {NULL}; + spi_bus_config_t buscfg = { + .miso_io_num = CONFIG_M_ROS_ETH_SPI_MISO_GPIO, + .mosi_io_num = CONFIG_M_ROS_ETH_SPI_MOSI_GPIO, + .sclk_io_num = CONFIG_M_ROS_ETH_SPI_SCLK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + }; + ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_M_ROS_ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); + + // Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.) + spi_eth_module_config_t spi_eth_module_config[CONFIG_M_ROS_SPI_ETHERNETS_NUM]; + INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 0); +#if CONFIG_M_ROS_SPI_ETHERNETS_NUM > 1 + INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 1); +#endif + + // Configure SPI interface and Ethernet driver for specific SPI module + esp_eth_mac_t *mac_spi[CONFIG_M_ROS_SPI_ETHERNETS_NUM]; + esp_eth_phy_t *phy_spi[CONFIG_M_ROS_SPI_ETHERNETS_NUM]; + esp_eth_handle_t eth_handle_spi[CONFIG_M_ROS_SPI_ETHERNETS_NUM] = {NULL}; +#if CONFIG_M_ROS_USE_KSZ8851SNL + spi_device_interface_config_t devcfg = { + .mode = 0, + .clock_speed_hz = CONFIG_M_ROS_ETH_SPI_CLOCK_MHZ * 1000 * 1000, + .queue_size = 20}; + + for (int i = 0; i < CONFIG_M_ROS_SPI_ETHERNETS_NUM; i++) + { + // Set SPI module Chip Select GPIO + devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio; + + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_M_ROS_ETH_SPI_HOST, &devcfg, &spi_handle[i])); + // KSZ8851SNL ethernet driver is based on spi driver + eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle[i]); + + // Set remaining GPIO numbers and configuration used by the SPI module + ksz8851snl_config.int_gpio_num = spi_eth_module_config[i].int_gpio; + phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr; + phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio; + + mac_spi[i] = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config_spi); + phy_spi[i] = esp_eth_phy_new_ksz8851snl(&phy_config_spi); + } +#elif CONFIG_M_ROS_USE_DM9051 + spi_device_interface_config_t devcfg = { + .command_bits = 1, + .address_bits = 7, + .mode = 0, + .clock_speed_hz = CONFIG_M_ROS_ETH_SPI_CLOCK_MHZ * 1000 * 1000, + .queue_size = 20}; + + for (int i = 0; i < CONFIG_M_ROS_SPI_ETHERNETS_NUM; i++) + { + // Set SPI module Chip Select GPIO + devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio; + + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_M_ROS_ETH_SPI_HOST, &devcfg, &spi_handle[i])); + // dm9051 ethernet driver is based on spi driver + eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle[i]); + + // Set remaining GPIO numbers and configuration used by the SPI module + dm9051_config.int_gpio_num = spi_eth_module_config[i].int_gpio; + phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr; + phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio; + + mac_spi[i] = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config_spi); + phy_spi[i] = esp_eth_phy_new_dm9051(&phy_config_spi); + } +#elif CONFIG_M_ROS_USE_W5500 + spi_device_interface_config_t devcfg = { + .command_bits = 16, // Actually it's the address phase in W5500 SPI frame + .address_bits = 8, // Actually it's the control phase in W5500 SPI frame + .mode = 0, + .clock_speed_hz = CONFIG_M_ROS_ETH_SPI_CLOCK_MHZ * 1000 * 1000, + .queue_size = 20}; + + for (int i = 0; i < CONFIG_M_ROS_SPI_ETHERNETS_NUM; i++) + { + // Set SPI module Chip Select GPIO + devcfg.spics_io_num = spi_eth_module_config[i].spi_cs_gpio; + + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_M_ROS_ETH_SPI_HOST, &devcfg, &spi_handle[i])); + // w5500 ethernet driver is based on spi driver + eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle[i]); + + // Set remaining GPIO numbers and configuration used by the SPI module + w5500_config.int_gpio_num = spi_eth_module_config[i].int_gpio; + phy_config_spi.phy_addr = spi_eth_module_config[i].phy_addr; + phy_config_spi.reset_gpio_num = spi_eth_module_config[i].phy_reset_gpio; + + mac_spi[i] = esp_eth_mac_new_w5500(&w5500_config, &mac_config_spi); + phy_spi[i] = esp_eth_phy_new_w5500(&phy_config_spi); + } +#endif // CONFIG_M_ROS_USE_W5500 + + for (int i = 0; i < CONFIG_M_ROS_SPI_ETHERNETS_NUM; i++) + { + esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac_spi[i], phy_spi[i]); + ESP_ERROR_CHECK(esp_eth_driver_install(ð_config_spi, ð_handle_spi[i])); + + /* The SPI Ethernet module might not have a burned factory MAC address, we cat to set it manually. + 02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control. + */ + ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle_spi[i], ETH_CMD_S_MAC_ADDR, (uint8_t[]){0x02, 0x00, 0x00, 0x12, 0x34, 0x56 + i})); + + // attach Ethernet driver to TCP/IP stack + ESP_ERROR_CHECK(esp_netif_attach(eth_netif_spi[i], esp_eth_new_netif_glue(eth_handle_spi[i]))); + } +#endif // CONFIG_ETH_USE_SPI_ETHERNET + + // Register user defined event handers + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); + +#if CONFIG_M_ROS_USE_INTERNAL_ETHERNET + /* start Ethernet driver state machine */ + ESP_ERROR_CHECK(esp_eth_start(eth_handle)); +#endif // CONFIG_M_ROS_USE_INTERNAL_ETHERNET +#if CONFIG_M_ROS_USE_SPI_ETHERNET + for (int i = 0; i < CONFIG_M_ROS_SPI_ETHERNETS_NUM; i++) + { + ESP_ERROR_CHECK(esp_eth_start(eth_handle_spi[i])); + } +#endif // CONFIG_M_ROS_USE_SPI_ETHERNET + + /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum + * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */ + EventBits_t bits = xEventGroupWaitBits(s_ethernet_event_group, + ETHERNET_CONNECTED_BIT | ETHERNET_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually + * happened. */ + if (bits & ETHERNET_CONNECTED_BIT) + { + ESP_LOGI(TAG, "Connected to network via ethernet."); + } + else if (bits & ETHERNET_FAIL_BIT) + { + ESP_LOGI(TAG, "Connection to network via ethernet failed."); + } + else + { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } +} + +uint32_t get_mros2_ip_addr(void) +{ + return mros2_ip_addr; +} + +#endif // CONFIG_M_ROS_ESP_NETIF_ENET \ No newline at end of file diff --git a/platform/ethernet/ethernet.h b/platform/ethernet/ethernet.h new file mode 100644 index 0000000..2e94b06 --- /dev/null +++ b/platform/ethernet/ethernet.h @@ -0,0 +1,38 @@ + +#include +#include "sdkconfig.h" + +#ifdef CONFIG_M_ROS_ESP_NETIF_ENET + +/* + * NOTE: + * This file is copied from esp-idf examples as the below, and modified for usage of mros2-esp32. + * https://github.com/espressif/esp-idf/blob/master/examples/wifi/getting_started/station/main/station_example_main.c + * Therefore, mROS-base org inherits the Public Domain (or CC0) LICENCE for this file from the original file. + */ + +#define ETHERNET_CONNECTED_BIT BIT0 +#define ETHERNET_FAIL_BIT BIT1 + +/* + * Caution: + * We have not tested the operation using STATIC_IP setting yet. + * So you may not un-comment the below line to use DHCP setting + */ +// #define STATIC_IP +#ifdef STATIC_IP +#define NETIF_IPADDR "192.168.11.107" +#define NETIF_NETMASK "255.255.255.0" +#define NETIF_GW "192.168.11.1" +#endif +#ifdef __cplusplus +extern "C" +{ +#endif + extern void init_network(void); + uint32_t get_mros2_ip_addr(void); +#ifdef __cplusplus +} +#endif + +#endif // CONFIG_M_ROS_ESP_NETIF_ENET diff --git a/platform/mros2-platform.cpp b/platform/mros2-platform.cpp index 91a9ac2..cf27047 100644 --- a/platform/mros2-platform.cpp +++ b/platform/mros2-platform.cpp @@ -30,7 +30,7 @@ */ extern "C" esp_err_t mros2_platform_network_connect(void) { - init_wifi(); + init_network(); osKernelStart(); /* get mros2 IP address and set it to RTPS */ diff --git a/platform/mros2-platform.h b/platform/mros2-platform.h index f4a0a5f..8d9a706 100644 --- a/platform/mros2-platform.h +++ b/platform/mros2-platform.h @@ -6,6 +6,7 @@ #include "cmsis_os.h" #include "wifi.h" +#include "ethernet.h" /* convert TARGET_NAME to put into message */ #define quote(x) std::string(q(x)) diff --git a/platform/wifi/wifi.c b/platform/wifi/wifi.c index 0748b45..42cc266 100644 --- a/platform/wifi/wifi.c +++ b/platform/wifi/wifi.c @@ -7,6 +7,8 @@ #include "wifi.h" +#ifdef CONFIG_M_ROS_ESP_NETIF_WLAN + #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" @@ -144,7 +146,7 @@ void wifi_init_sta(void) } } -void init_wifi(void) +void init_network(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) @@ -161,4 +163,6 @@ void init_wifi(void) uint32_t get_mros2_ip_addr(void) { return mros2_ip_addr; -} \ No newline at end of file +} + +#endif // CONFIG_M_ROS_ESP_NETIF_WLAN diff --git a/platform/wifi/wifi.h b/platform/wifi/wifi.h index 96d46e4..b08b23b 100644 --- a/platform/wifi/wifi.h +++ b/platform/wifi/wifi.h @@ -6,10 +6,13 @@ */ #include "esp_wifi_types.h" +#include "sdkconfig.h" -#define ESP_WIFI_SSID "SSID" -#define ESP_WIFI_PASS "PASS" -#define ESP_MAXIMUM_RETRY 3 +#ifdef CONFIG_M_ROS_ESP_NETIF_WLAN + +#define ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK #define WIFI_CONNECTED_BIT BIT0 @@ -29,8 +32,10 @@ #ifdef __cplusplus extern "C" { #endif -extern void init_wifi(void); +extern void init_network(void); uint32_t get_mros2_ip_addr(void); #ifdef __cplusplus } #endif + +#endif //CONFIG_M_ROS_ESP_NETIF_WLAN \ No newline at end of file From 04a2d75c3a19ec9b9ddd60b695fb1894dbd36c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sch=C3=A4fer?= Date: Sat, 20 Jan 2024 18:20:26 +0100 Subject: [PATCH 4/6] [SSC] Add readme for etherent and default settings for esp32-poe. --- Kconfig.projbuild | 6 +++--- README.md | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Kconfig.projbuild b/Kconfig.projbuild index 4c06f84..7aa3b9d 100644 --- a/Kconfig.projbuild +++ b/Kconfig.projbuild @@ -86,7 +86,7 @@ menu "mROS Settings" if M_ROS_USE_INTERNAL_ETHERNET choice M_ROS_ETH_PHY_MODEL prompt "Ethernet PHY Device" - default M_ROS_ETH_PHY_IP101 + default M_ROS_ETH_PHY_LAN8720 help Select the Ethernet PHY device to use in the example. @@ -186,7 +186,7 @@ menu "mROS Settings" config M_ROS_ETH_PHY_RST_GPIO int "PHY Reset GPIO number" - default 5 + default -1 help Set the GPIO number used to reset PHY chip. Set to -1 to disable PHY chip hardware reset. @@ -194,7 +194,7 @@ menu "mROS Settings" config M_ROS_ETH_PHY_ADDR int "PHY Address" range 0 31 - default 1 + default 0 help Set PHY address according your board schematic. endmenu diff --git a/README.md b/README.md index 4beeada..ef0864d 100644 --- a/README.md +++ b/README.md @@ -63,17 +63,24 @@ cd mros2-esp32 Note that you cannot change the directory name from `mros2-esp32` since it is used as the component name in `CMakeLists.txt`. -### Setup your SSID and PASS +### Select network platform -Please setup SSID and PASS for your Wi-Fi AP in `platform/wifi/wifi.h` (be careful that we should not commit and push your network environment to the world :D) +We support Wi-Fi and Ethernet. User `idf.py menuconfig` and go to `mROS Settings -> mROS network interface select` to choose the mode. Note that only one mode is supported at the same time. -```platform/wifi/wifi.h -#define ESP_WIFI_SSID "SSID" -#define ESP_WIFI_PASS "PASS" -``` +#### Setup your SSID and PASS + +Please setup SSID and PASS for your Wi-Fi AP in `idf.py menuconfig` and go to `mROS Settings -> Wifi Configuration` (be careful that we should not commit and push your network environment to the world :D) Again, make sure that its SSID assigns IP by DHCP and is dedicated to 2.4 GHz band. +### Setup ethernet + +See the [configuration guidline](https://github.com/espressif/esp-idf/blob/master/examples/ethernet/README.md#common-configurations) of espressif to setup your ethernet correctly. + +We selected the default settings to support the following boards out of the box: + +- [Olimex ESP32-POE (ISO/EA)](https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware) + ### Set target Go to `workspace/echoback_string/` and do the below to setup the target device. From df3dc225721e8ef17ca4649bce978f00fa904dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sch=C3=A4fer?= Date: Sat, 20 Jan 2024 18:22:15 +0100 Subject: [PATCH 5/6] [SSC] Add esp32-poe to supported board list. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ef0864d..b0691fb 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Please also check [mros2 repository](https://github.com/mROS-base/mros2) for mor - [M5Stack Core2](http://docs.m5stack.com/en/core/core2) - [M5Stack CoreS3](http://docs.m5stack.com/en/core/CoreS3) - [XIAO ESP32C3](https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html) (see [#7](https://github.com/mROS-base/mros2-esp32/issues/7)) + - [Olimex ESP32-POE (ISO/EA)](https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware) - Kernel: [ESP-IDF FreeRTOS](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos_idf.html) - Host environment - [ROS 2 Humble Hawksbill](https://docs.ros.org/en/humble/index.html) on Ubuntu 22.04 LTS From c5f9e26b275f6cd511299a44265ea9059660e335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sch=C3=A4fer?= Date: Mon, 22 Jan 2024 12:09:40 +0100 Subject: [PATCH 6/6] [SSC] Adding missing include in ethernet file for Windows. --- platform/ethernet/ethernet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/ethernet/ethernet.c b/platform/ethernet/ethernet.c index e1b691f..26e412e 100644 --- a/platform/ethernet/ethernet.c +++ b/platform/ethernet/ethernet.c @@ -14,6 +14,7 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" #include "esp_netif.h" #include "esp_eth.h" #include "esp_event.h"