diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 369489b6a9..593e80056f 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -44,6 +44,7 @@ from .const import ( KEY_BOARD, KEY_ESP8266, KEY_FLASH_SIZE, + KEY_LDSCRIPT, KEY_PIN_INITIAL_STATES, KEY_SERIAL1_REQUIRED, KEY_SERIAL_REQUIRED, @@ -404,7 +405,16 @@ async def to_code(config: ConfigType) -> None: # No ld script support ld_script = None elif ver <= cv.Version(2, 4, 2): - # Old ld script path + # Old ld script path; the modern per-board override names do + # not exist in this core's SDK, so it cannot be honored + if KEY_LDSCRIPT in board_data: + _LOGGER.warning( + "Board %s pins %s, which Arduino core %s cannot honor; " + "using the default flash layout", + config[CONF_BOARD], + board_data[KEY_LDSCRIPT], + ver, + ) ld_script = ld_scripts[0] else: # A per-board override preserves a layout the board shipped diff --git a/esphome/components/esp8266/boards.py b/esphome/components/esp8266/boards.py index 35d9d30e8c..268c6b50aa 100644 --- a/esphome/components/esp8266/boards.py +++ b/esphome/components/esp8266/boards.py @@ -1,4 +1,4 @@ -from .const import KEY_FLASH_SIZE +from .const import KEY_FLASH_SIZE, KEY_LDSCRIPT FLASH_SIZE_1_MB = 2**20 FLASH_SIZE_512_KB = FLASH_SIZE_1_MB // 2 @@ -166,7 +166,8 @@ ESP8266_BOARD_PINS = { } """ -BOARDS generate with: +BOARDS generate with (preserve per-board KEY_LDSCRIPT overrides such as +d1_wroom_02; the recipe emits only name/flash_size): git clone https://github.com/platformio/platform-espressif8266 for x in platform-espressif8266/boards/*.json; do @@ -192,7 +193,9 @@ def board_ld_script(board_data: dict) -> str: Single source of truth for the PlatformIO pinning in __init__ and the native generator's fallback, so the per-board rule cannot drift. """ - return board_data.get("ldscript", ESP8266_LD_SCRIPTS[board_data[KEY_FLASH_SIZE]][1]) + return board_data.get( + KEY_LDSCRIPT, ESP8266_LD_SCRIPTS[board_data[KEY_FLASH_SIZE]][1] + ) BOARDS = { @@ -219,7 +222,7 @@ BOARDS = { # (64 KB filesystem region); the flash-size default (2m.ld) would # move _FS_end and with it the preferences sector, wiping existing # devices' flash-backed state on update. - "ldscript": "eagle.flash.2m64.ld", + KEY_LDSCRIPT: "eagle.flash.2m64.ld", }, "d1": { "name": "WEMOS D1 R1", diff --git a/esphome/components/esp8266/const.py b/esphome/components/esp8266/const.py index 8729007e3a..c6f550c594 100644 --- a/esphome/components/esp8266/const.py +++ b/esphome/components/esp8266/const.py @@ -71,3 +71,6 @@ def enable_serial1() -> None: enable_serial1() """ CORE.data.setdefault(KEY_ESP8266, {})[KEY_SERIAL1_REQUIRED] = True + + +KEY_LDSCRIPT = "ldscript" diff --git a/tests/unit_tests/components/esp8266/test_boards.py b/tests/unit_tests/components/esp8266/test_boards.py new file mode 100644 index 0000000000..288e0a1eb9 --- /dev/null +++ b/tests/unit_tests/components/esp8266/test_boards.py @@ -0,0 +1,15 @@ +"""Tests for the per-board linker-script rule.""" + +from esphome.components.esp8266.boards import BOARDS, board_ld_script + + +def test_d1_wroom_02_keeps_its_shipped_layout() -> None: + """The override must survive a BOARDS regeneration or key typo: the + 2m.ld default moves _FS_end and the preferences sector on deployed + devices.""" + assert board_ld_script(BOARDS["d1_wroom_02"]) == "eagle.flash.2m64.ld" + + +def test_default_boards_use_the_flash_size_layout() -> None: + assert board_ld_script(BOARDS["d1_mini"]) == "eagle.flash.4m.ld" + assert board_ld_script(BOARDS["esp01_1m"]) == "eagle.flash.1m.ld"