Create a merged flash image from individual artifacts.
(self, output_path: Path, flash_size_mb: int = 4)
| 152 | self.bootloader_offset = get_bootloader_offset(board_name) |
| 153 | |
| 154 | def create_merged_image(self, output_path: Path, flash_size_mb: int = 4) -> bool: |
| 155 | """Create a merged flash image from individual artifacts.""" |
| 156 | if flash_size_mb not in VALID_FLASH_SIZES: |
| 157 | raise ValueError( |
| 158 | f"Invalid flash size: {flash_size_mb}MB. Must be in {VALID_FLASH_SIZES}" |
| 159 | ) |
| 160 | |
| 161 | if not self.artifacts.required_files_present: |
| 162 | raise ValueError( |
| 163 | f"Missing required files: {self.artifacts.missing_files()}" |
| 164 | ) |
| 165 | |
| 166 | flash_size = flash_size_mb * 1024 * 1024 |
| 167 | flash_data = bytearray(b"\xff" * flash_size) |
| 168 | |
| 169 | # Merge files at their offsets |
| 170 | self._write_at_offset( |
| 171 | flash_data, self.artifacts.bootloader, self.bootloader_offset |
| 172 | ) |
| 173 | self._write_at_offset( |
| 174 | flash_data, self.artifacts.partitions_bin, FLASH_OFFSETS.PARTITIONS |
| 175 | ) |
| 176 | self._write_at_offset( |
| 177 | flash_data, self.artifacts.boot_app0, FLASH_OFFSETS.BOOT_APP0 |
| 178 | ) |
| 179 | self._write_at_offset( |
| 180 | flash_data, self.artifacts.firmware, FLASH_OFFSETS.FIRMWARE |
| 181 | ) |
| 182 | |
| 183 | # Optional: SPIFFS if present (board-specific offset) |
| 184 | # Note: SPIFFS typically starts after firmware, offset varies by partition table |
| 185 | |
| 186 | output_path.write_bytes(flash_data) |
| 187 | return True |
| 188 | |
| 189 | def _write_at_offset( |
| 190 | self, flash_data: bytearray, file_path: Optional[Path], offset: int |