From 2805629c4bccd8aeb5a544568d91ba45a172faff Mon Sep 17 00:00:00 2001 From: Philippe G Date: Sun, 31 Oct 2021 14:47:28 -0700 Subject: [PATCH] add SPI ethernet --- components/raop/raop_sink.c | 15 ++-- components/services/accessors.c | 40 ++++++--- components/services/accessors.h | 8 +- components/wifi-manager/wifi_manager.c | 114 +++++++++++++++++++------ main/Kconfig.projbuild | 64 ++++++++++---- 5 files changed, 180 insertions(+), 61 deletions(-) diff --git a/components/raop/raop_sink.c b/components/raop/raop_sink.c index e654f112..51356d12 100644 --- a/components/raop/raop_sink.c +++ b/components/raop/raop_sink.c @@ -25,10 +25,10 @@ #define CONFIG_AIRPLAY_NAME "ESP32-AirPlay" #endif -typedef struct { +static EXT_RAM_ATTR struct raop_cb_s { raop_cmd_vcb_t cmd; raop_data_cb_t data; -} raop_cb_t; +} raop_cbs; log_level raop_loglevel = lINFO; log_level util_loglevel; @@ -204,10 +204,8 @@ static bool raop_sink_start(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) { * Airplay sink timer handler */ static void raop_start_handler( TimerHandle_t xTimer ) { - raop_cb_t *cbs = (raop_cb_t*) pvTimerGetTimerID (xTimer); - if (raop_sink_start(cbs->cmd, cbs->data)) { + if (raop_sink_start(raop_cbs.cmd, raop_cbs.data)) { xTimerDelete(xTimer, portMAX_DELAY); - free(cbs); } } @@ -216,10 +214,9 @@ static void raop_start_handler( TimerHandle_t xTimer ) { */ void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) { if (!raop_sink_start(cmd_cb, data_cb)) { - raop_cb_t *cbs = (raop_cb_t*) malloc(sizeof(raop_cb_t)); - cbs->cmd = cmd_cb; - cbs->data = data_cb; - TimerHandle_t timer = xTimerCreate("raopStart", 1000 / portTICK_RATE_MS, pdTRUE, cbs, raop_start_handler); + raop_cbs.cmd = cmd_cb; + raop_cbs.data = data_cb; + TimerHandle_t timer = xTimerCreate("raopStart", 5000 / portTICK_RATE_MS, pdTRUE, NULL, raop_start_handler); xTimerStart(timer, portMAX_DELAY); LOG_INFO( "delaying AirPlay start"); } diff --git a/components/services/accessors.c b/components/services/accessors.c index ac7ab5d2..63cbad8a 100644 --- a/components/services/accessors.c +++ b/components/services/accessors.c @@ -118,7 +118,7 @@ static void set_i2s_pin(char *config, i2s_pin_config_t *pin_config) { * Get i2s config structure from config string */ const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){ - static i2s_platform_config_t i2s_dac_pin = { + static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_pin = { .i2c_addr = -1, .sda= -1, .scl = -1, @@ -146,16 +146,26 @@ const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){ * Get eth config structure from config string */ const eth_config_t * config_get_eth_from_str(char * eth_config ){ - static eth_config_t eth_pin = { - .mdc = -1, - .mdio = -1, - .rst = -1, + static EXT_RAM_ATTR eth_config_t eth_pin = { + .rmii = false, + .model = "", }; char * p=NULL; + if ((p = strcasestr(eth_config, "model")) != NULL) sscanf(p, "%*[^=]=%15[^,]", eth_pin.model); if ((p = strcasestr(eth_config, "mdc")) != NULL) eth_pin.mdc = atoi(strchr(p, '=') + 1); if ((p = strcasestr(eth_config, "mdio")) != NULL) eth_pin.mdio = atoi(strchr(p, '=') + 1); if ((p = strcasestr(eth_config, "rst")) != NULL) eth_pin.rst = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(eth_config, "mosi")) != NULL) eth_pin.mosi = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(eth_config, "miso")) != NULL) eth_pin.miso = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(eth_config, "intr")) != NULL) eth_pin.intr = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(eth_config, "cs")) != NULL) eth_pin.cs = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(eth_config, "speed")) != NULL) eth_pin.speed = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(eth_config, "clk")) != NULL) eth_pin.clk = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(eth_config, "host")) != NULL) eth_pin.host = atoi(strchr(p, '=') + 1); + + if (strcasestr(eth_pin.model, "lan8720")) eth_pin.rmii = true; + return ð_pin; } @@ -164,7 +174,7 @@ const eth_config_t * config_get_eth_from_str(char * eth_config ){ */ const i2s_platform_config_t * config_spdif_get( ){ char * spdif_config = config_spdif_get_string(); - static i2s_platform_config_t i2s_dac_config; + static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_config; memcpy(&i2s_dac_config, config_get_i2s_from_str(spdif_config), sizeof(i2s_dac_config)); free(spdif_config); return &i2s_dac_config; @@ -175,7 +185,7 @@ const i2s_platform_config_t * config_spdif_get( ){ */ const i2s_platform_config_t * config_dac_get(){ char * spdif_config = get_dac_config_string(); - static i2s_platform_config_t i2s_dac_config; + static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_config; memcpy(&i2s_dac_config, config_get_i2s_from_str(spdif_config), sizeof(i2s_dac_config)); free(spdif_config); return &i2s_dac_config; @@ -185,9 +195,19 @@ const i2s_platform_config_t * config_dac_get(){ * Get ethernet config structure */ const eth_config_t * config_eth_get( ){ - char * config = config_alloc_get_str("eth_config", CONFIG_ETH_CONFIG, "mdc=" STR(CONFIG_MDC_IO) - ",mdio=" STR(CONFIG_MDIO_IO) ",do=" STR(CONFIG_PHY_RST_IO)); - static eth_config_t eth_config; + char * config = config_alloc_get_str("eth_config", CONFIG_ETH_CONFIG, "rst=" STR(CONFIG_ETH_PHY_RST_IO) +#if defined(CONFIG_ETH_LAN8720) + ",model=lan8720" +#elif defined(CONFIG_ETH_DM9051) + ",model=dm9051" +#endif + ",mdc=" STR(CONFIG_ETH_MDC_IO) ",mdio=" STR(CONFIG_ETH_MDIO_IO) + ",host=" STR(CONFIG_ETH_SPI_HOST) ",cs=" STR(CONFIG_ETH_SPI_CS_IO) + ",mosi=" STR(CONFIG_ETH_SPI_MOSI_IO) ",miso=" STR(CONFIG_ETH_SPI_MISO_IO) + ",intr=" STR(CONFIG_ETH_SPI_INTR_IO) + ",clk=" STR(CONFIG_ETH_SPI_CLK_IO) ",speed=" STR(CONFIG_ETH_SPI_SPEED) ); + static EXT_RAM_ATTR eth_config_t eth_config; + ESP_LOGD(TAG, "Ethernet config string %s", config); memcpy(ð_config, config_get_eth_from_str(config), sizeof(eth_config)); free(config); return ð_config; diff --git a/components/services/accessors.h b/components/services/accessors.h index 6cf59a2c..614d39cf 100644 --- a/components/services/accessors.h +++ b/components/services/accessors.h @@ -31,9 +31,13 @@ typedef struct { } display_config_t; typedef struct { - int mdc; - int mdio; + bool rmii; + char model[16]; int rst; + int mdc, mdio; + int host; + int cs, mosi, miso, intr, clk; + int speed; } eth_config_t; typedef struct { diff --git a/components/wifi-manager/wifi_manager.c b/components/wifi-manager/wifi_manager.c index 08d56fba..f333c7e8 100644 --- a/components/wifi-manager/wifi_manager.c +++ b/components/wifi-manager/wifi_manager.c @@ -295,6 +295,94 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base, } } +static void eth_init(void) { + esp_eth_mac_t *mac; + esp_eth_phy_t *phy; + esp_err_t err = ESP_OK; + eth_config_t const *eth = config_eth_get( ); + + // quick check if we have a valid ethernet configuration + if ((eth->mdc == -1 && eth->mosi == -1) || !*eth->model) { + ESP_LOGI(TAG, "No ethernet"); + return; + } + + tcpip_adapter_set_default_eth_handlers(); + esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL); + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + phy_config.phy_addr = 1; + phy_config.reset_gpio_num = eth->rst; + + if (eth->rmii) { +#ifdef CONFIG_ETH_USE_ESP32_EMAC + mac_config.smi_mdc_gpio_num = eth->mdc; + mac_config.smi_mdio_gpio_num = eth->mdio; + mac = esp_eth_mac_new_esp32(&mac_config); + phy = esp_eth_phy_new_lan8720(&phy_config); + ESP_LOGI(TAG, "Adding ethernet RMII with mdc %d and mdio %d", eth->mdc, eth->mdio); +#else + ESP_LOGE(TAG, "Ethernet RMII set but not included in compilation"); + return; +#endif + } else { +#ifdef CONFIG_ETH_SPI_ETHERNET_DM9051 + spi_device_handle_t spi_handle = NULL; + spi_host_device_t host = SPI3_HOST; + + if (eth->host != -1) { + // don't use system's shared SPI + spi_bus_config_t buscfg = { + .miso_io_num = eth->miso, + .mosi_io_num = eth->mosi, + .sclk_io_num = eth->clk, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + }; + + // can't use SPI0 + if (eth->host == 1) host = SPI2_HOST; + err |= spi_bus_initialize(host, &buscfg, 1); + } else { + // when we use shared SPI, we assume it has been initialized + host = spi_system_host; + } + + spi_device_interface_config_t devcfg = { + .command_bits = 1, + .address_bits = 7, + .mode = 0, + .clock_speed_hz = eth->speed, + .spics_io_num = eth->cs, + .queue_size = 20 + }; + + err |= spi_bus_add_device(host, &devcfg, &spi_handle); + + // dm9051 ethernet driver is based on spi driver + eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); + // we assume that isr has been installed already + dm9051_config.int_gpio_num = eth->intr; + mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); + phy = esp_eth_phy_new_dm9051(&phy_config); + ESP_LOGI(TAG, "Adding ethernet SPI on host %d with mosi %d and miso %d", host, eth->mosi, eth->miso); +#else + ESP_LOGE(TAG, "Ethernet SPI set but not included in compilation"); + return; +#endif + } + + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); + esp_eth_handle_t eth_handle = NULL; + err |= esp_eth_driver_install(&config, ð_handle); + err |= esp_eth_start(eth_handle); + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Can't install Ethernet driver %d", err); + } +} + void wifi_manager_init_wifi(){ /* event handler and event group for the wifi driver */ ESP_LOGD(TAG, "Initializing wifi. Creating event group"); @@ -317,31 +405,7 @@ void wifi_manager_init_wifi(){ ESP_LOGD(TAG, "Initializing wifi. Starting wifi"); ESP_ERROR_CHECK( esp_wifi_start() ); - //ETH - - eth_config_t const *eth = config_eth_get( ); - ESP_LOGE(TAG, "ETH MDC %d", eth->mdc); - ESP_LOGE(TAG, "ETH MDIO %d", eth->mdio); - ESP_LOGE(TAG, "ETH RST %d", eth->rst); - - ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers()); - ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL)); - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - phy_config.phy_addr = 1; - phy_config.reset_gpio_num = eth->rst; - - mac_config.smi_mdc_gpio_num = eth->mdc; - mac_config.smi_mdio_gpio_num = eth->mdio; - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); - esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); - - 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)); - ESP_ERROR_CHECK(esp_eth_start(eth_handle)); - //END_ETH + eth_init(); taskYIELD(); ESP_LOGD(TAG, "Initializing wifi. done"); diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index f408318d..b5b84113 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -98,7 +98,7 @@ menu "Squeezelite-ESP32" default "" config ETH_CONFIG string - default "" + default "" config DAC_CONTROLSET string default "{ \"init\": [ {\"reg\":41, \"val\":128}, {\"reg\":18, \"val\":255} ], \"poweron\": [ {\"reg\":18, \"val\":64, \"mode\":\"or\"} ], \"poweroff\": [ {\"reg\":18, \"val\":191, \"mode\":\"and\"} ] }" if TWATCH2020 @@ -107,23 +107,57 @@ menu "Squeezelite-ESP32" endmenu menu "Ethernet Options" - visible if BASIC_I2C_BT && ETH_USE_ESP32_EMAC - config ETH_MDC_IO - int "SMI MDC GPIO number" - default 23 - help - Set the GPIO number used by SMI MDC. - config ETH_MDIO_IO - int "SMI MDIO GPIO number" - default 18 - help - Set the GPIO number used by SMI MDIO. + visible if BASIC_I2C_BT && (ETH_USE_ESP32_EMAC || ETH_USE_SPI_ETHERNET) + choice + prompt "Ethernet Chipset" + default ETH_NODRIVER + config ETH_NODRIVER + bool "Defined in NVS" + config ETH_LAN8720 + bool "Microchip LAN8720 (RMII)" + config ETH_DM9051 + bool "Davicom 9051 (SPI)" + endchoice config ETH_PHY_RST_IO - int "PHY Reset GPIO number" - default 4 + int "PHY Reset GPIO number" if !ETH_NODRIVER + default -1 help Set the GPIO number used to reset PHY chip. - Set to -1 to disable PHY chip hardware reset. + Set to -1 to disable PHY chip hardware reset. + config ETH_MDC_IO + int "SMI MDC GPIO number" if ETH_LAN8720 + default -1 + help + Set the GPIO number used by SMI MDC. + config ETH_MDIO_IO + int "SMI MDIO GPIO number" if ETH_LAN8720 + default -1 + help + Set the GPIO number used by SMI MDIO. + config ETH_SPI_HOST + int "SPI host number (-1,1 or 2)" if ETH_DM9051 + default -1 + help + Set to -1 to use system's SPI config (see Various I/O) + Set to 2 or 3 to use a dedicated bus + config ETH_SPI_INTR_IO + int "interrupt" if ETH_DM9051 + default -1 + config ETH_SPI_CS_IO + int "Chip Select" if ETH_DM9051 + default -1 + config ETH_SPI_CLK_IO + int "SPI clock" if ETH_SPI_HOST != -1 && ETH_DM9051 + default -1 + config ETH_SPI_MOSI_IO + int "Data Out" if ETH_SPI_HOST != -1 && ETH_DM9051 + default -1 + config ETH_SPI_MISO_IO + int "Data In" if ETH_SPI_HOST != -1 && ETH_DM9051 + default -1 + config ETH_SPI_SPEED + int "SPI speed (Hz)" if ETH_SPI_HOST != -1 && ETH_DM9051 + default 20000000 endmenu menu "Audio settings"