diff --git a/README.md b/README.md index 685d9fc3..153928b1 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ Hold any button during startup to activate the Wi-Fi hotspot. Connect to it with ### Build fails -If the build fails due to memory limits, try disabling features you don’t plan to use in the [`.env`](https://github.com/VIPnytt/Frekvens/blob/main/.env). The [OTA](https://github.com/VIPnytt/Frekvens/wiki/Extensions#%EF%B8%8F-ota) extension is by far the largest one, and therefore a good first candidate to remove in order to free up memory for other features. +If the build fails due to size limits, try disabling features you don’t plan to use in the [`.env`](https://github.com/VIPnytt/Frekvens/blob/main/.env). The [OTA](https://github.com/VIPnytt/Frekvens/wiki/Extensions#%EF%B8%8F-ota) extension is by far the largest one, and therefore a good first candidate to remove in order to free up space for other features. ### Where is the web UI? diff --git a/partitions/2MB_no_ota.csv b/partitions/2MB_no_ota.csv index ffc8f25c..2a1f06dc 100644 --- a/partitions/2MB_no_ota.csv +++ b/partitions/2MB_no_ota.csv @@ -1,5 +1,5 @@ -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x5000, -littlefs, data, littlefs, 0xE000, 0x10000, -otadata, data, ota, 0x1E000, 0x2000, -app0, app, ota_0, 0x20000, 0x1E0000, +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +littlefs, data, littlefs, 0xE000, 0x10000, +otadata, data, ota, 0x1E000, 0x2000, +app0, app, ota_0, 0x20000, 0x1E0000, diff --git a/partitions/2MB_no_ota_rev2.csv b/partitions/2MB_no_ota_rev2.csv new file mode 100644 index 00000000..6dae763b --- /dev/null +++ b/partitions/2MB_no_ota_rev2.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +littlefs, data, littlefs, 0xE000, 0x20000, +otadata, data, ota, 0x2E000, 0x2000, +app0, app, ota_0, 0x30000, 0x1D0000, diff --git a/partitions/4MB_rev2.csv b/partitions/4MB_rev2.csv new file mode 100644 index 00000000..7db7741f --- /dev/null +++ b/partitions/4MB_rev2.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x8000, +coredump, data, coredump, 0x11000, 0xD000, +littlefs, data, littlefs, 0x1E000, 0x20000, +otadata, data, ota, 0x3E000, 0x2000, +app0, app, ota_0, 0x40000, 0x1E0000, +app1, app, ota_1, 0x220000, 0x1E0000, diff --git a/partitions/README.md b/partitions/README.md index e6770dfc..3945571f 100644 --- a/partitions/README.md +++ b/partitions/README.md @@ -1,20 +1,17 @@ # 💾 Partition tables -This directory contains predefined partition tables for different ESP32 flash sizes. +Partition tables for ESP32 boards with different flash sizes. Choose a layout matching your board, or let the build system select the best fit automatically. -> [!NOTE] -> ESP32 boards come with varying flash memory sizes. Newer models often include 8 MB, while most older boards have 4 MB. Boards with 2 MB, 16 MB, or 32 MB flash also exist. +## 📦 Predefined layouts -Use one of the predefined layouts below to match your board’s flash size: - -| Flash size | File | Feature capacity | OTA updates | -| ---------- | ----------------- | ----------------------- | ------------------ | -| 2 MB | `2MB_no_ota.csv` | :ballot_box_with_check: | :x: | -| 4 MB | `4MB_no_ota.csv` | :white_check_mark: | :x: | -| 4 MB | `4MB.csv` | :ballot_box_with_check: | :white_check_mark: | -| 8 MB | `8MB.csv` | :white_check_mark: | :white_check_mark: | -| 16 MB | `16MB.csv` | :white_check_mark: | :white_check_mark: | -| 32 MB | `32MB.csv` | :white_check_mark: | :white_check_mark: | +| Flash size | File | Feature capacity | OTA updates | +| ---------- | ---------------------- | ----------------------- | ------------------ | +| 2 MB | `2MB_no_ota_rev2.csv` | :ballot_box_with_check: | :x: | +| 4 MB | `4MB_no_ota.csv` | :white_check_mark: | :x: | +| 4 MB | `4MB_rev2.csv` | :ballot_box_with_check: | :white_check_mark: | +| 8 MB | `8MB.csv` | :white_check_mark: | :white_check_mark: | +| 16 MB | `16MB.csv` | :white_check_mark: | :white_check_mark: | +| 32 MB | `32MB.csv` | :white_check_mark: | :white_check_mark: | **Legend:** @@ -25,25 +22,34 @@ Use one of the predefined layouts below to match your board’s flash size: :x: — not available > [!TIP] -> Disable unneeded features in the [.env](https://github.com/VIPnytt/Frekvens/blob/main/.env) config file if the build is too large to fit. +> Disable unneeded features in the [.env](https://github.com/VIPnytt/Frekvens/blob/main/.env) config file if the build is too large to fit. OTA support requires space for two firmware images, so disabling OTA is often the most effective option on 4 MB boards. + +### Legacy layouts + +| Flash size | File | +| ---------- | ----------------- | +| 2 MB | `2MB_no_ota.csv` | +| 4 MB | `4MB.csv` | -## 2️⃣ 2 MB flash boards +These layouts are kept for backward compatibility, but are no longer recommended for new flashes. They were replaced in v2.5.0 by revised layouts with a better balance between firmware and filesystem space. -The `2MB_no_ota.csv` layout provides almost the same firmware capacity as `4MB.csv`, at the cost of [OTA](https://github.com/VIPnytt/Frekvens/wiki/Extensions#%EF%B8%8F-ota) support. +## 2️⃣ 2 MB flash memory + +Boards with only 2 MB flash memory have very limited space, so only a minimal feature set with no OTA-capability is possible. Configure in [platformio.ini](https://github.com/VIPnytt/Frekvens/blob/main/platformio.ini): ```ini -board_build.partitions = partitions/2MB_no_ota_fs.csv +board_build.partitions = partitions/2MB_no_ota_rev2.csv ``` -## 4️⃣ 4 MB flash boards +## 4️⃣ 4 MB flash memory -Depending on configuration, there’s two alternatives. +There are two main options, depending on whether OTA updates are desired. ### No OTA -The `4MB_no_ota.csv` layout provides the same firmware capacity as `8MB.csv`, at the cost of the [OTA](https://github.com/VIPnytt/Frekvens/wiki/Extensions#%EF%B8%8F-ota) ability. +The 4 MB flash layout without OTA support is recommended for users who want the full feature set and are comfortable with manual updates. Configure in [platformio.ini](https://github.com/VIPnytt/Frekvens/blob/main/platformio.ini): @@ -53,17 +59,17 @@ board_build.partitions = partitions/4MB_no_ota.csv ### With OTA -The `4MB.csv` layout provides a flexible configuration with [OTA](https://github.com/VIPnytt/Frekvens/wiki/Extensions#%EF%B8%8F-ota) updates, [web app](https://github.com/VIPnytt/Frekvens/wiki/Extensions#-web-app) access, and a limited firmware capacity. +The 4 MB flash layout with OTA support provides a limited feature set, but allows for convenient over-the-air updates. Recommended for users who prioritize ease of updates and are willing to accept some limitations in features. Configure in [platformio.ini](https://github.com/VIPnytt/Frekvens/blob/main/platformio.ini): ```ini -board_build.partitions = partitions/4MB.csv +board_build.partitions = partitions/4MB_rev2.csv ``` -## 8️⃣ 8 MB, 16 MB, and 32 MB flash boards +## 8️⃣ 8 MB+ flash memory -These provides a comfortable and flexible configuration without any compromises. +These layouts all include OTA support and provide a comfortable, flexible configuration without compromises. Configure in [platformio.ini](https://github.com/VIPnytt/Frekvens/blob/main/platformio.ini): @@ -78,3 +84,5 @@ board_build.partitions = partitions/16MB.csv ```ini board_build.partitions = partitions/32MB.csv ``` + +Boards with more than 32 MB flash memory should use the 32 MB layout. diff --git a/scripts/src/components/Deprecated.py b/scripts/src/components/Deprecated.py index d3124c46..c2ee17e9 100644 --- a/scripts/src/components/Deprecated.py +++ b/scripts/src/components/Deprecated.py @@ -15,7 +15,7 @@ class Deprecated: - MIGRATIONS: list[tuple[str, str, str, str]] = [ + FEATURES: list[tuple[str, str, str, str]] = [ ("MODE_ARTNET", "Art-Net", Stream.ENV_OPTION, Stream.NAME), ("MODE_BOLDCLOCK", "Bold clock", Clock.ENV_OPTION, Clock.NAME), ("MODE_DISTRIBUTEDDISPLAYPROTOCOL", "Distributed Display Protocol", Stream.ENV_OPTION, Stream.NAME), @@ -45,7 +45,7 @@ def initialize(self) -> None: self._platformio_ini() def _env(self) -> None: - for old_option, old_name, new_option, new_name in self.MIGRATIONS: + for old_option, old_name, new_option, new_name in self.FEATURES: if old_option in self.project.dotenv: if new_option == Weather.ENV_OPTION: weather_option = f"WEATHER_{old_option.removeprefix('MODE_')}" @@ -71,15 +71,29 @@ def _env(self) -> None: del self.project.dotenv[old_option] def _platformio_ini(self) -> None: - option = "board_build.embed_files" - path = "firmware/embed/x509_crt_bundle.bin" - paths = self.project.env.GetProjectOption(option, None) - if paths and ((isinstance(paths, list) and path in paths) or (isinstance(paths, str) and paths == path)): - logging.warning("'%s = %s' is deprecated and should be removed from platformio.ini.", option, path) - _path = pathlib.Path(path) + embed_option = "board_build.embed_files" + embed_path = "firmware/embed/x509_crt_bundle.bin" + embed_paths = self.project.env.GetProjectOption(embed_option, None) + if embed_paths and ( + (isinstance(embed_paths, list) and embed_path in embed_paths) + or (isinstance(embed_paths, str) and embed_paths == embed_path) + ): + logging.warning( + "'%s = %s' is deprecated and should be removed from platformio.ini.", embed_option, embed_path + ) + _path = pathlib.Path(embed_path) if not _path.exists(): _path.parent.mkdir(parents=True, exist_ok=True) _path.write_bytes(b"\x00") + partition_table = self.project.env.GetProjectOption("board_build.partitions", None) + if "partitions/2MB_no_ota.csv" == partition_table: + logging.warning( + "The '2MB_no_ota.csv' partition table is deprecated, please migrate to the newer '2MB_no_ota_rev2.csv' table" + ) + elif "partitions/4MB.csv" == partition_table: + logging.warning( + "The '4MB.csv' partition table is deprecated, please migrate to the newer '4MB_rev2.csv' table" + ) @staticmethod def clean() -> None: diff --git a/scripts/src/components/Partition.py b/scripts/src/components/Partition.py index 3bd24684..870ff4b9 100644 --- a/scripts/src/components/Partition.py +++ b/scripts/src/components/Partition.py @@ -28,17 +28,13 @@ def _get_flash_size(self) -> str: return size if size else self.project.env.BoardConfig().get("upload.flash_size") def _lookup_table(self, flash_size: str) -> pathlib.Path | None: - if flash_size in [ - "2MB", - ]: - return self.path / f"{flash_size}_no_ota.csv" - elif flash_size in [ - "4MB", - ]: + if flash_size == "2MB": + return self.path / "2MB_no_ota_rev2.csv" + elif flash_size == "4MB": return ( - self.path / f"{flash_size}.csv" + self.path / "4MB_rev2.csv" if Ota.ENV_OPTION in self.project.dotenv and self.project.dotenv[Ota.ENV_OPTION] == "true" - else self.path / f"{flash_size}_no_ota.csv" + else self.path / "4MB_no_ota.csv" ) elif flash_size in [ "8MB", @@ -46,4 +42,6 @@ def _lookup_table(self, flash_size: str) -> pathlib.Path | None: "32MB", ]: return self.path / f"{flash_size}.csv" + elif flash_size.endswith("MB") and int(flash_size[:-2]) >= 32: + return self.path / "32MB.csv" return None diff --git a/scripts/src/extensions/Ota.py b/scripts/src/extensions/Ota.py index 341e0247..a0184cc4 100644 --- a/scripts/src/extensions/Ota.py +++ b/scripts/src/extensions/Ota.py @@ -1,6 +1,6 @@ import hashlib +import logging import typing -import warnings if typing.TYPE_CHECKING: from ..Frekvens import Frekvens @@ -23,10 +23,7 @@ def configure(self) -> None: def validate(self) -> None: if "no_ota" in str(self.project.partition.table): if self.ENV_OPTION in self.project.dotenv and self.project.dotenv[self.ENV_OPTION] != "false": - warnings.warn( - f"{self.ENV_OPTION}: Partition table does not support OTA updates.", - UserWarning, - ) + logging.error(f"{self.ENV_OPTION}: Partition table does not support {self.NAME} updates.") else: self.project.dotenv[self.ENV_OPTION] = "false" self.project.ota = None diff --git a/scripts/src/extensions/WebApp.py b/scripts/src/extensions/WebApp.py index b71372cc..8614523a 100644 --- a/scripts/src/extensions/WebApp.py +++ b/scripts/src/extensions/WebApp.py @@ -1,5 +1,6 @@ import dotenv import gzip +import logging import nodejs_wheel import os import pathlib @@ -28,10 +29,7 @@ def validate(self) -> None: self.project.webapp = None elif "no_fs" in str(self.project.partition.table): if self.ENV_OPTION in self.project.dotenv and self.project.dotenv[self.ENV_OPTION] == "true": - warnings.warn( - f"{self.ENV_OPTION}: Partition table has no filesystem support.", - UserWarning, - ) + logging.error(f"{self.ENV_OPTION}: Partition table has no filesystem support.") elif WebSocket.ENV_OPTION not in self.project.dotenv or self.project.dotenv[WebSocket.ENV_OPTION] == "false": warnings.warn( f"{WebSocket.ENV_OPTION}: {WebSocket.NAME} is required by {self.NAME}.",