|
1 | | -# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD |
| 1 | +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD |
2 | 2 | # SPDX-License-Identifier: Apache-2.0 |
3 | | - |
4 | 3 | import json |
5 | 4 | import os |
6 | 5 | import shlex |
7 | 6 | import signal |
8 | 7 | import sys |
9 | | -from typing import Any, Dict, List, Optional |
| 8 | +from typing import Any |
| 9 | +from typing import Dict |
| 10 | +from typing import List |
| 11 | +from typing import Optional |
10 | 12 |
|
11 | 13 | import click |
12 | 14 | from idf_py_actions.global_options import global_options |
13 | | -from idf_py_actions.tools import (PropertyDict, RunTool, ensure_build_directory, get_default_serial_port, |
14 | | - get_sdkconfig_value, run_target) |
| 15 | +from idf_py_actions.tools import ensure_build_directory |
| 16 | +from idf_py_actions.tools import get_default_serial_port |
| 17 | +from idf_py_actions.tools import get_sdkconfig_value |
| 18 | +from idf_py_actions.tools import PropertyDict |
| 19 | +from idf_py_actions.tools import run_target |
| 20 | +from idf_py_actions.tools import RunTool |
15 | 21 |
|
16 | 22 | PYTHON = sys.executable |
17 | 23 |
|
|
34 | 40 | } |
35 | 41 |
|
36 | 42 |
|
37 | | -def yellow_print(message, newline='\n'): # type: (str, Optional[str]) -> None |
| 43 | +def yellow_print(message: str, newline: Optional[str]='\n') -> None: |
38 | 44 | """Print a message to stderr with yellow highlighting """ |
39 | 45 | sys.stderr.write('%s%s%s%s' % ('\033[0;33m', message, '\033[0m', newline)) |
40 | 46 | sys.stderr.flush() |
@@ -212,6 +218,47 @@ def ota_targets(target_name: str, ctx: click.core.Context, args: PropertyDict) - |
212 | 218 | ensure_build_directory(args, ctx.info_name) |
213 | 219 | run_target(target_name, args, {'ESPBAUD': str(args.baud), 'ESPPORT': args.port}) |
214 | 220 |
|
| 221 | + def merge_bin(action: str, |
| 222 | + ctx: click.core.Context, |
| 223 | + args: PropertyDict, |
| 224 | + output: str, |
| 225 | + format: str, |
| 226 | + md5_disable: str, |
| 227 | + flash_offset: str, |
| 228 | + fill_flash_size: str) -> None: |
| 229 | + ensure_build_directory(args, ctx.info_name) |
| 230 | + project_desc = _get_project_desc(ctx, args) |
| 231 | + merge_bin_args = [PYTHON, '-m', 'esptool'] |
| 232 | + target = project_desc['target'] |
| 233 | + merge_bin_args += ['--chip', target] |
| 234 | + merge_bin_args += ['merge_bin'] # needs to be after the --chip option |
| 235 | + if not output: |
| 236 | + if format in ('raw', 'uf2'): |
| 237 | + output = 'merged-binary.bin' |
| 238 | + elif format == 'hex': |
| 239 | + output = 'merged-binary.hex' |
| 240 | + merge_bin_args += ['-o', output] |
| 241 | + if format: |
| 242 | + merge_bin_args += ['-f', format] |
| 243 | + if md5_disable: |
| 244 | + if format != 'uf2': |
| 245 | + yellow_print('idf.py merge-bin: --md5-disable is only valid for UF2 format. Option will be ignored.') |
| 246 | + else: |
| 247 | + merge_bin_args += ['--md5-disable'] |
| 248 | + if flash_offset: |
| 249 | + if format != 'raw': |
| 250 | + yellow_print('idf.py merge-bin: --flash-offset is only valid for RAW format. Option will be ignored.') |
| 251 | + else: |
| 252 | + merge_bin_args += ['-t', flash_offset] |
| 253 | + if fill_flash_size: |
| 254 | + if format != 'raw': |
| 255 | + yellow_print('idf.py merge-bin: --fill-flash-size is only valid for RAW format, option will be ignored.') |
| 256 | + else: |
| 257 | + merge_bin_args += ['--fill-flash-size', fill_flash_size] |
| 258 | + merge_bin_args += ['@flash_args'] |
| 259 | + print(f'Merged binary {output} will be created in the build directory...') |
| 260 | + RunTool('merge_bin', merge_bin_args, args.build_dir, build_dir=args.build_dir, hints=not args.no_hints)() |
| 261 | + |
215 | 262 | BAUD_AND_PORT = [BAUD_RATE, PORT] |
216 | 263 | flash_options = BAUD_AND_PORT + [ |
217 | 264 | { |
@@ -252,6 +299,37 @@ def ota_targets(target_name: str, ctx: click.core.Context, args: PropertyDict) - |
252 | 299 | 'help': 'Erase entire flash chip.', |
253 | 300 | 'options': BAUD_AND_PORT, |
254 | 301 | }, |
| 302 | + 'merge-bin': { |
| 303 | + 'callback': merge_bin, |
| 304 | + 'options': [ |
| 305 | + { |
| 306 | + 'names': ['--output', '-o'], |
| 307 | + 'help': ('Output filename'), |
| 308 | + 'type': click.Path(), |
| 309 | + }, |
| 310 | + { |
| 311 | + 'names': ['--format', '-f'], |
| 312 | + 'help': ('Format of the output file'), |
| 313 | + 'type': click.Choice(['hex', 'uf2', 'raw']), |
| 314 | + 'default': 'raw', |
| 315 | + }, |
| 316 | + { |
| 317 | + 'names': ['--md5-disable'], |
| 318 | + 'is_flag': True, |
| 319 | + 'help': ('[ONLY UF2] Disable MD5 checksum in UF2 output.'), |
| 320 | + }, |
| 321 | + { |
| 322 | + 'names': ['--flash-offset', '-t'], |
| 323 | + 'help': ('[ONLY RAW] Flash offset where the output file will be flashed.'), |
| 324 | + }, |
| 325 | + { |
| 326 | + 'names': ['--fill-flash-size'], |
| 327 | + 'help': ('[ONLY RAW] If set, the final binary file will be padded with FF bytes up to this flash size.'), |
| 328 | + 'type': click.Choice(['256KB', '512KB', '1MB', '2MB', '4MB', '8MB', '16MB', '32MB', '64MB', '128MB']), |
| 329 | + }, |
| 330 | + ], |
| 331 | + 'dependencies': ['all'], # all = build |
| 332 | + }, |
255 | 333 | 'monitor': { |
256 | 334 | 'callback': |
257 | 335 | monitor, |
|
0 commit comments