From 65ef2613cfae5d2d3306aab18b7febcb331ea7c4 Mon Sep 17 00:00:00 2001 From: TD-er Date: Sun, 7 May 2023 16:41:17 +0200 Subject: [PATCH] [ESP32-S2/S3/C3] Update user configurable SPI bus in ESPEasy. --- docs/source/ESPEasy/ESPchips.rst | 11 +++- platformio_esp32s3_envs.ini | 33 ++++++---- src/src/DataStructs_templ/SettingsStruct.cpp | 14 ++-- src/src/DataTypes/SPI_options.cpp | 58 +++++++++++++++-- src/src/DataTypes/SPI_options.h | 68 +++++++++++++++++++- src/src/Helpers/Hardware.cpp | 10 ++- src/src/WebServer/HardwarePage.cpp | 11 +++- 7 files changed, 171 insertions(+), 34 deletions(-) diff --git a/docs/source/ESPEasy/ESPchips.rst b/docs/source/ESPEasy/ESPchips.rst index 7685ae68a..ca728ac32 100644 --- a/docs/source/ESPEasy/ESPchips.rst +++ b/docs/source/ESPEasy/ESPchips.rst @@ -166,7 +166,7 @@ ESPEasy does support a number of variants of the processors manufactured by Espr * - DAC - 0 - 2*8-bit DAC - - 0 + - 2*8-bit DAC - 0 - 0 - 0 @@ -512,6 +512,15 @@ The only drawback is that it doesn't support a RMII ethernet interface. .. note:: Support for the ESP32-S3 is very preliminary, as in it is hardly tested (as of May 2023) +PSRAM support on ESP32-S3 is a bit of a mess. + +Some ESP32-S3 chips have embedded PSRAM. +When they do, you need to have the SPI bus for memory/flash set to QIO/OPI mode. +With QIO/QSPI mode, the PSRAM will not be detected. + +However, if the chip does not have PSRAM and the SPI bus is set to QIO/OPI mode, the flash will lockup and no longer respond when accessing it. +So for now only the ``max_ESP32s3_16M8M_LittleFS_PSRAM`` build will be set to use QIO/OPI mode. + ESP32-C3 ======== diff --git a/platformio_esp32s3_envs.ini b/platformio_esp32s3_envs.ini index a717997da..97f4fcc16 100644 --- a/platformio_esp32s3_envs.ini +++ b/platformio_esp32s3_envs.ini @@ -25,7 +25,7 @@ board_build.filesystem = littlefs [env:custom_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_BUILD_CUSTOM extra_scripts = ${esp32s3_common.extra_scripts} @@ -33,7 +33,7 @@ extra_scripts = ${esp32s3_common.extra_scripts} [env:neopixel_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DFEATURE_ARDUINO_OTA=1 -DFEATURE_SD=1 @@ -42,7 +42,7 @@ build_flags = ${esp32s3_common.build_flags} [env:custom_IR_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_BUILD_CUSTOM -DPLUGIN_BUILD_IR @@ -56,46 +56,46 @@ extra_scripts = ${esp32s3_common.extra_scripts} [env:normal_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi [env:collection_A_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_SET_COLLECTION_ESP32 -DCOLLECTION_USE_RTTTL [env:collection_B_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_SET_COLLECTION_B_ESP32 -DCOLLECTION_USE_RTTTL [env:collection_C_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_SET_COLLECTION_C_ESP32 -DCOLLECTION_USE_RTTTL [env:collection_D_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_SET_COLLECTION_D_ESP32 -DCOLLECTION_USE_RTTTL [env:collection_E_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_SET_COLLECTION_E_ESP32 -DCOLLECTION_USE_RTTTL [env:collection_F_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -DPLUGIN_SET_COLLECTION_F_ESP32 -DCOLLECTION_USE_RTTTL @@ -103,25 +103,25 @@ build_flags = ${esp32s3_common.build_flags} [env:energy_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -D PLUGIN_ENERGY_COLLECTION [env:display_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -D PLUGIN_DISPLAY_COLLECTION [env:climate_ESP32s3_4M316k] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi build_flags = ${esp32s3_common.build_flags} -D PLUGIN_CLIMATE_COLLECTION [env:max_ESP32s3_16M8M_LittleFS] extends = esp32s3_common -board = esp32s3-qio_opi +board = esp32s3-qio_qspi board_upload.flash_size = 16MB lib_ignore = ${esp32_always.lib_ignore} ESP32_ping @@ -134,3 +134,8 @@ extra_scripts = ${esp32_common.extra_scripts} board_build.filesystem = littlefs board_build.partitions = esp32_partition_app4096k_spiffs8124k.csv + +[env:max_ESP32s3_16M8M_LittleFS_PSRAM] +extends = max_ESP32s3_16M8M_LittleFS +board = esp32s3-qio_opi + diff --git a/src/src/DataStructs_templ/SettingsStruct.cpp b/src/src/DataStructs_templ/SettingsStruct.cpp index 836c40bbe..33f207e6c 100644 --- a/src/src/DataStructs_templ/SettingsStruct.cpp +++ b/src/src/DataStructs_templ/SettingsStruct.cpp @@ -794,18 +794,22 @@ bool SettingsStruct_tmpl::getSPI_pins(int8_t spi_gpios[3]) const { const SPI_Options_e SPI_selection = static_cast(InitSPI); switch (SPI_selection) { - case SPI_Options_e::Vspi: + case SPI_Options_e::Vspi_Fspi: { - spi_gpios[0] = 18; spi_gpios[1] = 19; spi_gpios[2] = 23; + spi_gpios[0] = VSPI_FSPI_SCK; + spi_gpios[1] = VSPI_FSPI_MISO; + spi_gpios[2] = VSPI_FSPI_MOSI; break; } +#ifdef ESP32_CLASSIC case SPI_Options_e::Hspi: { - spi_gpios[0] = 14; // HSPI_SCLK - spi_gpios[1] = 12; // HSPI_MISO - spi_gpios[2] = 13; // HSPI_MOSI + spi_gpios[0] = HSPI_SCLK; + spi_gpios[1] = HSPI_MISO; + spi_gpios[2] = HSPI_MOSI; break; } +#endif case SPI_Options_e::UserDefined: { spi_gpios[0] = SPI_SCLK_pin; diff --git a/src/src/DataTypes/SPI_options.cpp b/src/src/DataTypes/SPI_options.cpp index bab3f6788..6111d8ec8 100644 --- a/src/src/DataTypes/SPI_options.cpp +++ b/src/src/DataTypes/SPI_options.cpp @@ -1,14 +1,62 @@ #include "../DataTypes/SPI_options.h" +// ESP32 VSPI: +// SCK = 18 +// MISO = 19 +// MOSI = 23 +// ESP32 HSPI: +// SCK = 14 +// MISO = 12 +// MOSI = 13 + + +// ESP32-S2 FSPI: +// SCK = 36 +// MISO = 37 +// MOSI = 35 + +// ESP32-S3 FSPI: +// SCK = 36 +// MISO = 37 +// MOSI = 35 + +// ESP32-C3 SPI: +// SCK = 4 +// MISO = 5 +// MOSI = 6 + + +# if CONFIG_IDF_TARGET_ESP32S3 // ESP32-S3 +#define VSPI_FSPI_SHORT_STRING "FSPI" +#define VSPI_FSPI_OPTIONS_STRING "FSPI: CLK=GPIO-36, MISO=GPIO-37, MOSI=GPIO-35" +# elif CONFIG_IDF_TARGET_ESP32S2 // ESP32-S2 +#define VSPI_FSPI_SHORT_STRING "FSPI" +#define VSPI_FSPI_OPTIONS_STRING "FSPI: CLK=GPIO-36, MISO=GPIO-37, MOSI=GPIO-35" +# elif CONFIG_IDF_TARGET_ESP32C3 // ESP32-C3 +#define VSPI_FSPI_SHORT_STRING "SPI" +#define VSPI_FSPI_OPTIONS_STRING "SPI: CLK=GPIO-4, MISO=GPIO-5, MOSI=GPIO-6" +# elif CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 +#define VSPI_FSPI_SHORT_STRING "VSPI" +#define VSPI_FSPI_OPTIONS_STRING "VSPI: CLK=GPIO-18, MISO=GPIO-19, MOSI=GPIO-23" + +# else // if CONFIG_IDF_TARGET_ESP32S2 +# error Target CONFIG_IDF_TARGET is not supported +# endif // if CONFIG_IDF_TARGET_ESP32S2 + + + + #ifdef ESP32 const __FlashStringHelper* getSPI_optionToString(SPI_Options_e option) { switch (option) { case SPI_Options_e::None: return F("Disabled"); - case SPI_Options_e::Vspi: - return F("VSPI: CLK=GPIO-18, MISO=GPIO-19, MOSI=GPIO-23"); + case SPI_Options_e::Vspi_Fspi: + return F(VSPI_FSPI_OPTIONS_STRING); +#ifdef ESP32_CLASSIC case SPI_Options_e::Hspi: return F("HSPI: CLK=GPIO-14, MISO=GPIO-12, MOSI=GPIO-13"); +#endif case SPI_Options_e::UserDefined: return F("User-defined: CLK, MISO, MOSI GPIO-pins"); } @@ -19,10 +67,12 @@ const __FlashStringHelper* getSPI_optionToShortString(SPI_Options_e option) { switch (option) { case SPI_Options_e::None: return F("Disabled"); - case SPI_Options_e::Vspi: - return F("VSPI"); + case SPI_Options_e::Vspi_Fspi: + return F(VSPI_FSPI_SHORT_STRING); +#ifdef ESP32_CLASSIC case SPI_Options_e::Hspi: return F("HSPI"); +#endif case SPI_Options_e::UserDefined: return F("User-defined SPI"); } diff --git a/src/src/DataTypes/SPI_options.h b/src/src/DataTypes/SPI_options.h index 71b767e29..8dd96e4a2 100644 --- a/src/src/DataTypes/SPI_options.h +++ b/src/src/DataTypes/SPI_options.h @@ -3,10 +3,76 @@ #include + +// ESP32 classic has default pins for HSPI. +// All others don't, as any pin can be used. + +// Default SPI host: +// ESP32 classic: VSPI +// ESP32-C3 : FSPI +// ESP32-S2/S3 : FSPI + +// ESP32 classic: +// SPI_HOST = SPI1_HOST // Only usable on ESP32 +// HSPI_HOST = SPI2_HOST +// VSPI_HOST = SPI3_HOST +// +// ESP32-S2: +// FSPI_HOST = SPI2_HOST +// HSPI_HOST = SPI3_HOST +// +// ESP32-S3: +// FSPI_HOST = SPI2_HOST +// HSPI_HOST = SPI3_HOST +// +// ESP32-C3: +// FSPI_HOST = SPI2_HOST + + +// SPIx_HOST defined in enum spi_host_device_t in hal/spi_types.h +// Aliases for each platform defined in ESPEasy: src/include/esp32x_fixes.h + +// HSPI option is disabled for now on other than ESP32_CLASSIC. +// Should be added later as "Custom HSPI" when we support multiple SPI busses. + +# if CONFIG_IDF_TARGET_ESP32S3 // ESP32-S3 +#define VSPI_FSPI_SCK 36 +#define VSPI_FSPI_MISO 37 +#define VSPI_FSPI_MOSI 35 +# elif CONFIG_IDF_TARGET_ESP32S2 // ESP32-S2 +#define VSPI_FSPI_SCK 36 +#define VSPI_FSPI_MISO 37 +#define VSPI_FSPI_MOSI 35 +# elif CONFIG_IDF_TARGET_ESP32C3 // ESP32-C3 +#define VSPI_FSPI_SCK 4 +#define VSPI_FSPI_MISO 5 +#define VSPI_FSPI_MOSI 6 +# elif CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 +#define VSPI_FSPI_SCK 18 +#define VSPI_FSPI_MISO 19 +#define VSPI_FSPI_MOSI 23 + +# define HSPI_SCLK 14 +# define HSPI_MISO 12 +# define HSPI_MOSI 13 +# define HSPI_SS 15 + +# else // if CONFIG_IDF_TARGET_ESP32S2 +# error Target CONFIG_IDF_TARGET is not supported +# endif // if CONFIG_IDF_TARGET_ESP32S2 + + enum class SPI_Options_e { // Do not change values as this is stored in the settings! None = 0, - Vspi = 1, + Vspi_Fspi = 1, // Default SPI bus +#ifdef ESP32_CLASSIC Hspi = 2, +#endif + + // UserDefined is using the default SPI bus. + // For ESP32 classic, this is called VSPI + // For later versions it is called FSPI + // N.B. the ESP32-C3 does not seem to name these as there is no SPI3_HOST. UserDefined = 9 // Leave some room for other, possible future, hardware-related options }; diff --git a/src/src/Helpers/Hardware.cpp b/src/src/Helpers/Hardware.cpp index 1f1b3cdec..101c3dc19 100644 --- a/src/src/Helpers/Hardware.cpp +++ b/src/src/Helpers/Hardware.cpp @@ -195,15 +195,13 @@ void hardwareInit() const SPI_Options_e SPI_selection = static_cast(Settings.InitSPI); switch (SPI_selection) { +#ifdef ESP32_CLASSIC case SPI_Options_e::Hspi: { - # define HSPI_MISO 12 - # define HSPI_MOSI 13 - # define HSPI_SCLK 14 - # define HSPI_SS 15 SPI.begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI); // HSPI break; } +#endif case SPI_Options_e::UserDefined: { SPI.begin(Settings.SPI_SCLK_pin, @@ -211,9 +209,9 @@ void hardwareInit() Settings.SPI_MOSI_pin); // User-defined SPI break; } - case SPI_Options_e::Vspi: + case SPI_Options_e::Vspi_Fspi: { - SPI.begin(); // VSPI + SPI.begin(); // Default SPI bus break; } case SPI_Options_e::None: diff --git a/src/src/WebServer/HardwarePage.cpp b/src/src/WebServer/HardwarePage.cpp index 356e35b65..c518e9940 100644 --- a/src/src/WebServer/HardwarePage.cpp +++ b/src/src/WebServer/HardwarePage.cpp @@ -197,16 +197,21 @@ void handle_hardware() { false); const __FlashStringHelper * spi_options[] = { getSPI_optionToString(SPI_Options_e::None), - getSPI_optionToString(SPI_Options_e::Vspi), + getSPI_optionToString(SPI_Options_e::Vspi_Fspi), + #ifdef ESP32_CLASSIC getSPI_optionToString(SPI_Options_e::Hspi), + #endif getSPI_optionToString(SPI_Options_e::UserDefined)}; const int spi_index[] = { static_cast(SPI_Options_e::None), - static_cast(SPI_Options_e::Vspi), + static_cast(SPI_Options_e::Vspi_Fspi), + #ifdef ESP32_CLASSIC static_cast(SPI_Options_e::Hspi), + #endif static_cast(SPI_Options_e::UserDefined) }; - addFormSelector_script(F("Init SPI"), F("initspi"), 4, spi_options, spi_index, nullptr, Settings.InitSPI, F("spiOptionChanged(this)")); + constexpr size_t nrOptions = sizeof(spi_index) / sizeof(spi_index[0]); + addFormSelector_script(F("Init SPI"), F("initspi"), nrOptions, spi_options, spi_index, nullptr, Settings.InitSPI, F("spiOptionChanged(this)")); // User-defined pins addFormPinSelect(PinSelectPurpose::SPI, formatGpioName_output(F("CLK")), F("spipinsclk"), Settings.SPI_SCLK_pin); addFormPinSelect(PinSelectPurpose::SPI_MISO, formatGpioName_input(F("MISO")), F("spipinmiso"), Settings.SPI_MISO_pin);