diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 4ecb247ec3..5e23c6250b 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -1,6 +1,7 @@ #include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/version.h" +#include "esphome/core/esphal.h" #ifdef USE_STATUS_LED #include "esphome/components/status_led/status_led.h" @@ -58,6 +59,9 @@ void Application::setup() { ESP_LOGI(TAG, "setup() finished successfully!"); this->schedule_dump_config(); this->calculate_looping_components_(); + + // Dummy function to link some symbols into the binary. + force_link_symbols(); } void Application::loop() { uint32_t new_app_state = 0; diff --git a/esphome/core/esphal.cpp b/esphome/core/esphal.cpp index 2389a2a7f6..90707016c3 100644 --- a/esphome/core/esphal.cpp +++ b/esphome/core/esphal.cpp @@ -271,6 +271,22 @@ ISRInternalGPIOPin *GPIOPin::to_isr() const { this->gpio_read_, this->gpio_mask_, this->inverted_); } +void force_link_symbols() { +#ifdef ARDUINO_ARCH_ESP8266 + // Tasmota uses magic bytes in the binary to check if an OTA firmware is compatible + // with their settings - ESPHome uses a different settings system (that can also survive + // erases). So set magic bytes indicating all tasmota versions are supported. + // This only adds 12 bytes of binary size, which is an acceptable price to pay for easier support + // for Tasmota. + // https://github.com/arendst/Tasmota/blob/b05301b1497942167a015a6113b7f424e42942cd/tasmota/settings.ino#L346-L380 + // https://github.com/arendst/Tasmota/blob/b05301b1497942167a015a6113b7f424e42942cd/tasmota/i18n.h#L652-L654 + const static uint32_t TASMOTA_MAGIC_BYTES[] PROGMEM = {0x5AA55AA5, 0xFFFFFFFF, 0xA55AA55A}; + // Force link symbol by using a volatile integer (GCC attribute used does not work because of LTO) + volatile int x = 0; + x = TASMOTA_MAGIC_BYTES[x]; +#endif +} + } // namespace esphome #ifdef ARDUINO_ESP8266_RELEASE_2_3_0 diff --git a/esphome/core/esphal.h b/esphome/core/esphal.h index 453e094acc..809c7d91b5 100644 --- a/esphome/core/esphal.h +++ b/esphome/core/esphal.h @@ -116,4 +116,12 @@ class GPIOPin { template void GPIOPin::attach_interrupt(void (*func)(T *), T *arg, int mode) const { this->attach_interrupt_(reinterpret_cast(func), arg, mode); } +/** This function can be used by the HAL to force-link specific symbols + * into the generated binary without modifying the linker script. + * + * It is called by the application very early on startup and should not be used for anything + * other than forcing symbols to be linked. + */ +void force_link_symbols(); + } // namespace esphome