diff --git a/tasmota/tasmota_support/support_esp.ino b/tasmota/tasmota_support/support_esp32.ino similarity index 84% rename from tasmota/tasmota_support/support_esp.ino rename to tasmota/tasmota_support/support_esp32.ino index ce75c9bfc..d6c8ccc7e 100644 --- a/tasmota/tasmota_support/support_esp.ino +++ b/tasmota/tasmota_support/support_esp32.ino @@ -1,218 +1,15 @@ /* - support_esp.ino - ESP specific code for Tasmota + support_esp32.ino - ESP32 specific support for Tasmota - Copyright (C) 2021 Theo Arends / Jörg Schüler-Maroldt + SPDX-FileCopyrightText: 2023 Theo Arends - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . + SPDX-License-Identifier: GPL-3.0-only */ -/*********************************************************************************************\ - * ESP8266 and ESP32 specific code - * - * At the end the common Tasmota calls are provided -\*********************************************************************************************/ - -/*********************************************************************************************\ - * ESP8266 Support -\*********************************************************************************************/ - -#ifdef ESP8266 - -extern "C" { -extern struct rst_info resetInfo; -} - -/*********************************************************************************************\ - * Core overrides executed by core -\*********************************************************************************************/ - -// Add below line to tasmota_globals.h -// extern "C" void resetPins(); -// -// This function overrules __resetPins() which is executed by core init() as initPins() in core_esp8266_wiring.cpp -// -// 20221229 - (v12.3.1.2) Enabled with additional check to execute on power on only to fix relay clicks on power on -// 20200321 - (v8.2.0.1) Disable core functionality to fix relay clicks on restart after OTA - make function return without setting pinMode -void resetPins() { - if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) { - // Only perform at power on - for (int i = 0; i <= 5; ++i) { - pinMode(i, INPUT); - } - // pins 6-11 are used for the SPI flash interface ESP8266 - for (int i = 12; i <= 16; ++i) { - pinMode(i, INPUT); - } - } -} - -/*********************************************************************************************\ - * Hardware related -\*********************************************************************************************/ - -void HwWdtDisable(void) { - *((volatile uint32_t*) 0x60000900) &= ~(1); // Hardware WDT OFF -} - -void HwWdtEnable(void) { - *((volatile uint32_t*) 0x60000900) |= 1; // Hardware WDT ON -} - -void WdtDisable(void) { - ESP.wdtDisable(); - HwWdtDisable(); -} - -void WdtEnable(void) { - HwWdtEnable(); - ESP.wdtEnable(0); -} - -/*********************************************************************************************\ - * ESP8266 specifics -\*********************************************************************************************/ - -uint32_t ESP_ResetInfoReason(void) { - return resetInfo.reason; -} - -String ESP_getResetReason(void) { - return ESP.getResetReason(); -} - -uint32_t ESP_getChipId(void) { - return ESP.getChipId(); -} - -uint32_t ESP_getFreeSketchSpace(void) { - return ESP.getFreeSketchSpace(); -} - -uint32_t ESP_getSketchSize(void) { - return ESP.getSketchSize(); -} - -uint32_t ESP_getFreeHeap(void) { - return ESP.getFreeHeap(); -} - -uint32_t ESP_getFlashChipId(void) { - return ESP.getFlashChipId(); -} - -uint32_t ESP_getFlashChipRealSize(void) { - return ESP.getFlashChipRealSize(); -} - -uint32_t ESP_getFlashChipSize(void) { - return ESP.getFlashChipSize(); -} - -void ESP_Restart(void) { -// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 - ESP.reset(); -} - -uint32_t FlashWriteStartSector(void) { - return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side -} - -uint32_t FlashWriteMaxSector(void) { - return (((uint32_t)&_FS_start - 0x40200000) / SPI_FLASH_SEC_SIZE) - 2; -} - -uint8_t* FlashDirectAccess(void) { - return (uint8_t*)(0x40200000 + (FlashWriteStartSector() * SPI_FLASH_SEC_SIZE)); -} - -void *special_malloc(uint32_t size) { - return malloc(size); -} - -void *special_realloc(void *ptr, size_t size) { - return realloc(ptr, size); -} - -void *special_calloc(size_t num, size_t size) { - return calloc(num, size); -} - -String GetDeviceHardware(void) { - /* - ESP8266 SoCs - - 32-bit MCU & 2.4 GHz Wi-Fi - - High-performance 160 MHz single-core CPU - - +19.5 dBm output power ensures a good physical range - - Sleep current is less than 20 μA, making it suitable for battery-powered and wearable-electronics applications - - Peripherals include UART, GPIO, I2C, I2S, SDIO, PWM, ADC and SPI - */ - // esptool.py get_efuses - uint32_t efuse0 = *(uint32_t*)(0x3FF00050); -// uint32_t efuse1 = *(uint32_t*)(0x3FF00054); - uint32_t efuse2 = *(uint32_t*)(0x3FF00058); - uint32_t efuse3 = *(uint32_t*)(0x3FF0005C); - - bool r0_4 = efuse0 & (1 << 4); // ESP8285 - bool r2_16 = efuse2 & (1 << 16); // ESP8285 - if (r0_4 || r2_16) { // ESP8285 - // 1M 2M 2M 4M flash size - // r0_4 1 1 0 0 - bool r3_25 = efuse3 & (1 << 25); // flash matrix 0 0 1 1 - bool r3_26 = efuse3 & (1 << 26); // flash matrix 0 1 0 1 - bool r3_27 = efuse3 & (1 << 27); // flash matrix 0 0 0 0 - uint32_t pkg_version = 0; - if (!r3_27) { - if (r0_4 && !r3_25) { - pkg_version = (r3_26) ? 2 : 1; - } - else if (!r0_4 && r3_25) { - pkg_version = (r3_26) ? 4 : 2; - } - } - bool max_temp = efuse0 & (1 << 5); // Max flash temperature (0 = 85C, 1 = 105C) - switch (pkg_version) { - case 1: - if (max_temp) { return F("ESP8285H08"); } // 1M flash - else { return F("ESP8285N08"); } - case 2: - if (max_temp) { return F("ESP8285H16"); } // 2M flash - else { return F("ESP8285N16"); } - case 4: - if (max_temp) { return F("ESP8285H32"); } // 4M flash - else { return F("ESP8285N32"); } - } - return F("ESP8285"); - } - return F("ESP8266EX"); -} - -String GetDeviceHardwareRevision(void) { - // No known revisions for ESP8266/85 - return GetDeviceHardware(); -} - -String GetCodeCores(void) { - return F(""); -} - -#endif - -/*********************************************************************************************\ - * ESP32 Support -\*********************************************************************************************/ - #ifdef ESP32 +/*********************************************************************************************\ + * ESP32, ESP32-S2, ESP32-S3, ESP32-C2, ESP32-C3, ESP32-C6 and ESP32-H2 Support +\*********************************************************************************************/ #include "soc/soc.h" #include "soc/spi_reg.h" @@ -233,6 +30,8 @@ String GetCodeCores(void) { #define ESP32_ARCH "esp32c3" #elif CONFIG_IDF_TARGET_ESP32C6 #define ESP32_ARCH "esp32c6" +#elif CONFIG_IDF_TARGET_ESP32H2 + #define ESP32_ARCH "esp32h2" #else #define ESP32_ARCH "" #endif @@ -256,6 +55,8 @@ String GetCodeCores(void) { #include "esp32c3/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C6 // ESP32-C6 #include "esp32c6/rom/rtc.h" + #elif CONFIG_IDF_TARGET_ESP32H2 // ESP32-H2 + #include "esp32h2/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -440,6 +241,9 @@ extern "C" { #elif CONFIG_IDF_TARGET_ESP32C6 // ESP32-C6 #include "esp32c6/rom/spi_flash.h" #define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c6 is located at 0x0000 + #elif CONFIG_IDF_TARGET_ESP32H2 // ESP32-H2 + #include "esp32h2/rom/spi_flash.h" + #define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000 #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -707,6 +511,15 @@ uint32_t ESP_getFreeHeap(void) { return heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); } +uint32_t ESP_getFreeHeap1024(void) { + return ESP_getFreeHeap() / 1024; +} +/* +float ESP_getFreeHeap1024(void) { + return ((float)ESP_getFreeHeap()) / 1024; +} +*/ + uint32_t ESP_getMaxAllocHeap(void) { // arduino returns IRAM but we want only DRAM #ifdef USE_GT911 // GT911 IRQ crashes with heap_caps_get_largest_free_block @@ -1140,21 +953,6 @@ bool CanUsePSRAM(void) { return true; } -#endif // ESP32 - -/*********************************************************************************************\ - * ESP Support -\*********************************************************************************************/ - -uint32_t ESP_getFreeHeap1024(void) { - return ESP_getFreeHeap() / 1024; -} -/* -float ESP_getFreeHeap1024(void) { - return ((float)ESP_getFreeHeap()) / 1024; -} -*/ - /*********************************************************************************************\ * High entropy hardware random generator * Thanks to DigitalAlchemist @@ -1166,18 +964,12 @@ float ESP_getFreeHeap1024(void) { // Based on code from https://raw.githubusercontent.com/espressif/esp-idf/master/components/esp32/hw_random.c uint32_t HwRandom(void) { -#if ESP8266 - // https://web.archive.org/web/20160922031242/http://esp8266-re.foogod.com/wiki/Random_Number_Generator - #define _RAND_ADDR 0x3FF20E44UL -#endif // ESP8266 -#ifdef ESP32 #if ESP_IDF_VERSION_MAJOR >= 5 // See for more info on the HW RNG: // https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/system/random.html return esp_random(); -#endif +#else #define _RAND_ADDR 0x3FF75144UL -#endif // ESP32 static uint32_t last_ccount = 0; uint32_t ccount; uint32_t result = 0; @@ -1187,5 +979,8 @@ uint32_t HwRandom(void) { } while (ccount - last_ccount < 64); last_ccount = ccount; return result ^ *(volatile uint32_t *)_RAND_ADDR; -#undef _RAND_ADDR + #undef _RAND_ADDR +#endif // ESP_IDF_VERSION_MAJOR >= 5 } + +#endif // ESP32 \ No newline at end of file diff --git a/tasmota/tasmota_support/support_esp8266.ino b/tasmota/tasmota_support/support_esp8266.ino new file mode 100644 index 000000000..00df1731b --- /dev/null +++ b/tasmota/tasmota_support/support_esp8266.ino @@ -0,0 +1,221 @@ +/* + support_esp8266.ino - ESP8266 specific support for Tasmota + + SPDX-FileCopyrightText: 2023 Theo Arends + + SPDX-License-Identifier: GPL-3.0-only +*/ + +#ifdef ESP8266 +/*********************************************************************************************\ + * ESP8266 and ESP8285 Support +\*********************************************************************************************/ + +extern "C" { +extern struct rst_info resetInfo; +} + +/*********************************************************************************************\ + * Core overrides executed by core +\*********************************************************************************************/ + +// Add below line to tasmota_globals.h +// extern "C" void resetPins(); +// +// This function overrules __resetPins() which is executed by core init() as initPins() in core_esp8266_wiring.cpp +// +// 20221229 - (v12.3.1.2) Enabled with additional check to execute on power on only to fix relay clicks on power on +// 20200321 - (v8.2.0.1) Disable core functionality to fix relay clicks on restart after OTA - make function return without setting pinMode +void resetPins() { + if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) { + // Only perform at power on + for (int i = 0; i <= 5; ++i) { + pinMode(i, INPUT); + } + // pins 6-11 are used for the SPI flash interface ESP8266 + for (int i = 12; i <= 16; ++i) { + pinMode(i, INPUT); + } + } +} + +/*********************************************************************************************\ + * Hardware related +\*********************************************************************************************/ + +void HwWdtDisable(void) { + *((volatile uint32_t*) 0x60000900) &= ~(1); // Hardware WDT OFF +} + +void HwWdtEnable(void) { + *((volatile uint32_t*) 0x60000900) |= 1; // Hardware WDT ON +} + +void WdtDisable(void) { + ESP.wdtDisable(); + HwWdtDisable(); +} + +void WdtEnable(void) { + HwWdtEnable(); + ESP.wdtEnable(0); +} + +/*********************************************************************************************\ + * ESP8266 specifics +\*********************************************************************************************/ + +uint32_t ESP_ResetInfoReason(void) { + return resetInfo.reason; +} + +String ESP_getResetReason(void) { + return ESP.getResetReason(); +} + +uint32_t ESP_getChipId(void) { + return ESP.getChipId(); +} + +uint32_t ESP_getFreeSketchSpace(void) { + return ESP.getFreeSketchSpace(); +} + +uint32_t ESP_getSketchSize(void) { + return ESP.getSketchSize(); +} + +uint32_t ESP_getFreeHeap(void) { + return ESP.getFreeHeap(); +} + +uint32_t ESP_getFreeHeap1024(void) { + return ESP_getFreeHeap() / 1024; +} +/* +float ESP_getFreeHeap1024(void) { + return ((float)ESP_getFreeHeap()) / 1024; +} +*/ + +uint32_t ESP_getFlashChipId(void) { + return ESP.getFlashChipId(); +} + +uint32_t ESP_getFlashChipRealSize(void) { + return ESP.getFlashChipRealSize(); +} + +uint32_t ESP_getFlashChipSize(void) { + return ESP.getFlashChipSize(); +} + +void ESP_Restart(void) { +// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 + ESP.reset(); +} + +uint32_t FlashWriteStartSector(void) { + return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side +} + +uint32_t FlashWriteMaxSector(void) { + return (((uint32_t)&_FS_start - 0x40200000) / SPI_FLASH_SEC_SIZE) - 2; +} + +uint8_t* FlashDirectAccess(void) { + return (uint8_t*)(0x40200000 + (FlashWriteStartSector() * SPI_FLASH_SEC_SIZE)); +} + +void *special_malloc(uint32_t size) { + return malloc(size); +} + +void *special_realloc(void *ptr, size_t size) { + return realloc(ptr, size); +} + +void *special_calloc(size_t num, size_t size) { + return calloc(num, size); +} + +String GetDeviceHardware(void) { + /* + ESP8266 SoCs + - 32-bit MCU & 2.4 GHz Wi-Fi + - High-performance 160 MHz single-core CPU + - +19.5 dBm output power ensures a good physical range + - Sleep current is less than 20 μA, making it suitable for battery-powered and wearable-electronics applications + - Peripherals include UART, GPIO, I2C, I2S, SDIO, PWM, ADC and SPI + */ + // esptool.py get_efuses + uint32_t efuse0 = *(uint32_t*)(0x3FF00050); +// uint32_t efuse1 = *(uint32_t*)(0x3FF00054); + uint32_t efuse2 = *(uint32_t*)(0x3FF00058); + uint32_t efuse3 = *(uint32_t*)(0x3FF0005C); + + bool r0_4 = efuse0 & (1 << 4); // ESP8285 + bool r2_16 = efuse2 & (1 << 16); // ESP8285 + if (r0_4 || r2_16) { // ESP8285 + // 1M 2M 2M 4M flash size + // r0_4 1 1 0 0 + bool r3_25 = efuse3 & (1 << 25); // flash matrix 0 0 1 1 + bool r3_26 = efuse3 & (1 << 26); // flash matrix 0 1 0 1 + bool r3_27 = efuse3 & (1 << 27); // flash matrix 0 0 0 0 + uint32_t pkg_version = 0; + if (!r3_27) { + if (r0_4 && !r3_25) { + pkg_version = (r3_26) ? 2 : 1; + } + else if (!r0_4 && r3_25) { + pkg_version = (r3_26) ? 4 : 2; + } + } + bool max_temp = efuse0 & (1 << 5); // Max flash temperature (0 = 85C, 1 = 105C) + switch (pkg_version) { + case 1: + if (max_temp) { return F("ESP8285H08"); } // 1M flash + else { return F("ESP8285N08"); } + case 2: + if (max_temp) { return F("ESP8285H16"); } // 2M flash + else { return F("ESP8285N16"); } + case 4: + if (max_temp) { return F("ESP8285H32"); } // 4M flash + else { return F("ESP8285N32"); } + } + return F("ESP8285"); + } + return F("ESP8266EX"); +} + +String GetDeviceHardwareRevision(void) { + // No known revisions for ESP8266/85 + return GetDeviceHardware(); +} + +String GetCodeCores(void) { + return F(""); +} + +/*********************************************************************************************\ + * High entropy hardware random generator + * Thanks to DigitalAlchemist +\*********************************************************************************************/ + +// Based on code from https://raw.githubusercontent.com/espressif/esp-idf/master/components/esp32/hw_random.c +uint32_t HwRandom(void) { + // https://web.archive.org/web/20160922031242/http://esp8266-re.foogod.com/wiki/Random_Number_Generator + #define _RAND_ADDR 0x3FF20E44UL + static uint32_t last_ccount = 0; + uint32_t ccount; + uint32_t result = 0; + do { + ccount = ESP.getCycleCount(); + result ^= *(volatile uint32_t *)_RAND_ADDR; + } while (ccount - last_ccount < 64); + last_ccount = ccount; + return result ^ *(volatile uint32_t *)_RAND_ADDR; + #undef _RAND_ADDR +} + +#endif // ESP8266 \ No newline at end of file