11import json
2+ import logging
23import os
34from typing import ClassVar
45
@@ -13,60 +14,88 @@ class ArduinoApp(App):
1314 sketch (str): Sketch name.
1415 fqbn (str): Fully Qualified Board Name.
1516 target (str) : ESPxx chip.
16- flash_files (List[Tuple[int, str, str]]): List of (offset, file path, encrypted) of files need to be flashed in.
17+ flash_settings (dict[str, str]): Flash settings for the target.
18+ bootloader_offset (int): Bootloader offset.
19+ binary_file (str): Merged binary file path.
20+ elf_file (str): ELF file path.
1721 """
1822
19- #: dict of flash settings
20- flash_settings : ClassVar [dict [str , dict [str , str ]]] = {
21- 'esp32' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
22- 'esp32c2' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '60m' },
23- 'esp32c3' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
24- 'esp32c5' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
25- 'esp32c6' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
26- 'esp32c61' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
27- 'esp32h2' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '48m' },
28- 'esp32p4' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
29- 'esp32s2' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
30- 'esp32s3' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
31- }
32-
33- #: dict of binaries' offset.
34- binary_offsets : ClassVar [dict [str , list [int ]]] = {
35- 'esp32' : [0x1000 , 0x8000 , 0x10000 ],
36- 'esp32c2' : [0x0 , 0x8000 , 0x10000 ],
37- 'esp32c3' : [0x0 , 0x8000 , 0x10000 ],
38- 'esp32c5' : [0x2000 , 0x8000 , 0x10000 ],
39- 'esp32c6' : [0x0 , 0x8000 , 0x10000 ],
40- 'esp32c61' : [0x0 , 0x8000 , 0x10000 ],
41- 'esp32h2' : [0x0 , 0x8000 , 0x10000 ],
42- 'esp32p4' : [0x2000 , 0x8000 , 0x10000 ],
43- 'esp32s2' : [0x1000 , 0x8000 , 0x10000 ],
44- 'esp32s3' : [0x0 , 0x8000 , 0x10000 ],
45- }
46-
4723 def __init__ (
4824 self ,
4925 ** kwargs ,
5026 ):
5127 super ().__init__ (** kwargs )
5228
53- self .sketch = os .path .basename (self .app_path )
29+ # If no valid binary path is found, assume the build directory is the app path
30+ if not self .binary_path and self .app_path :
31+ self .binary_path = self .app_path
32+
33+ # Extract sketch name from binary files in the build directory
34+ self .sketch = self ._get_sketch_name (self .binary_path )
5435 self .fqbn = self ._get_fqbn (self .binary_path )
5536 self .target = self .fqbn .split (':' )[2 ]
56- self .flash_files = self ._get_bin_files (self .binary_path , self .sketch , self .target )
37+ self .flash_settings = self ._get_flash_settings ()
38+ self .bootloader_offset = self ._get_bootloader_offset ()
39+ self .binary_file = os .path .realpath (os .path .join (self .binary_path , self .sketch + '.ino.merged.bin' ))
5740 self .elf_file = os .path .realpath (os .path .join (self .binary_path , self .sketch + '.ino.elf' ))
5841
59- def _get_fqbn (self , build_path ) -> str :
42+ logging .debug (f'Sketch name: { self .sketch } ' )
43+ logging .debug (f'FQBN: { self .fqbn } ' )
44+ logging .debug (f'Target: { self .target } ' )
45+ logging .debug (f'Flash settings: { self .flash_settings } ' )
46+ logging .debug (f'Bootloader offset: { self .bootloader_offset } ' )
47+ logging .debug (f'Binary file: { self .binary_file } ' )
48+ logging .debug (f'ELF file: { self .elf_file } ' )
49+
50+ def _get_sketch_name (self , build_path : str ) -> str :
51+ """Extract sketch name from binary files in the build directory."""
52+ if not build_path or not os .path .isdir (build_path ):
53+ logging .warning (f'No build path found. Using default sketch name "sketch".' )
54+ return 'sketch'
55+
56+ # Look for .ino.bin or .ino.merged.bin files
57+ for filename in os .listdir (build_path ):
58+ if filename .endswith ('.ino.bin' ) or filename .endswith ('.ino.merged.bin' ):
59+ # Extract sketch name (everything before .ino.bin or .ino.merged.bin)
60+ if filename .endswith ('.ino.merged.bin' ):
61+ return filename [:- len ('.ino.merged.bin' )]
62+ else :
63+ return filename [:- len ('.ino.bin' )]
64+
65+ # If no .ino.bin or .ino.merged.bin files found, raise an error
66+ raise ValueError (f'No .ino.bin or .ino.merged.bin file found in { build_path } ' )
67+
68+ def _get_fqbn (self , build_path : str ) -> str :
69+ """Get FQBN from build.options.json file."""
6070 options_file = os .path .realpath (os .path .join (build_path , 'build.options.json' ))
6171 with open (options_file ) as f :
6272 options = json .load (f )
6373 fqbn = options ['fqbn' ]
6474 return fqbn
6575
66- def _get_bin_files (self , build_path , sketch , target ) -> list [tuple [int , str , bool ]]:
67- bootloader = os .path .realpath (os .path .join (build_path , sketch + '.ino.bootloader.bin' ))
68- partitions = os .path .realpath (os .path .join (build_path , sketch + '.ino.partitions.bin' ))
69- app = os .path .realpath (os .path .join (build_path , sketch + '.ino.bin' ))
70- files = [bootloader , partitions , app ]
71- offsets = self .binary_offsets [target ]
72- return [(offsets [i ], files [i ], False ) for i in range (3 )]
76+ def _get_bootloader_offset (self ) -> int :
77+ """Get bootloader offset from flash_args file."""
78+ flash_args_file = os .path .realpath (os .path .join (self .binary_path , 'flash_args' ))
79+ with open (flash_args_file ) as f :
80+ bootloader_offset = int (f .readlines ()[1 ].split (' ' )[0 ].strip (), 16 )
81+
82+ if bootloader_offset is None :
83+ raise ValueError (f'Bootloader offset not found in { flash_args_file } ' )
84+
85+ return bootloader_offset
86+
87+ def _get_flash_settings (self ) -> dict [str , str ]:
88+ """Get flash settings from flash_args file."""
89+ flash_args_file = os .path .realpath (os .path .join (self .binary_path , 'flash_args' ))
90+ with open (flash_args_file ) as f :
91+ flash_args = f .readline ().split (' ' )
92+
93+ flash_settings = {}
94+ for i , arg in enumerate (flash_args ):
95+ if arg .startswith ('--' ):
96+ flash_settings [arg [2 :].strip ()] = flash_args [i + 1 ].strip ()
97+
98+ if flash_settings == {}:
99+ raise ValueError (f'Flash settings not found in { flash_args_file } ' )
100+
101+ return flash_settings
0 commit comments