| 
42 | 42 | # Don't change this, or output from argparse won't match up.  | 
43 | 43 | INDENT = ' ' * 2  | 
44 | 44 | 
 
  | 
 | 45 | +IGNORED_RUN_ONCE_PRIORITY = -1  | 
 | 46 | +SOC_FILE_RUN_ONCE_DEFAULT_PRIORITY = 0  | 
 | 47 | +BOARD_FILE_RUN_ONCE_DEFAULT_PRIORITY = 10  | 
 | 48 | + | 
45 | 49 | if log.VERBOSE >= log.VERBOSE_NORMAL:  | 
46 | 50 |     # Using level 1 allows sub-DEBUG levels of verbosity. The  | 
47 | 51 |     # west.log module decides whether or not to actually print the  | 
@@ -96,6 +100,13 @@ class ImagesFlashed:  | 
96 | 100 |     flashed: int = 0  | 
97 | 101 |     total: int = 0  | 
98 | 102 | 
 
  | 
 | 103 | +@dataclass  | 
 | 104 | +class SocBoardFilesProcessing:  | 
 | 105 | +    filename: str  | 
 | 106 | +    board: bool = False  | 
 | 107 | +    priority: int = IGNORED_RUN_ONCE_PRIORITY  | 
 | 108 | +    yaml: object = None  | 
 | 109 | + | 
99 | 110 | def command_verb(command):  | 
100 | 111 |     return "flash" if command.name == "flash" else "debug"  | 
101 | 112 | 
 
  | 
@@ -178,6 +189,10 @@ def do_run_common(command, user_args, user_runner_args, domain_file=None):  | 
178 | 189 |     # images for a given board.  | 
179 | 190 |     board_image_count = defaultdict(ImagesFlashed)  | 
180 | 191 | 
 
  | 
 | 192 | +    highest_priority = IGNORED_RUN_ONCE_PRIORITY  | 
 | 193 | +    highest_entry = None  | 
 | 194 | +    check_files = []  | 
 | 195 | + | 
181 | 196 |     if user_args.context:  | 
182 | 197 |         dump_context(command, user_args, user_runner_args)  | 
183 | 198 |         return  | 
@@ -223,48 +238,58 @@ def do_run_common(command, user_args, user_runner_args, domain_file=None):  | 
223 | 238 |             # Load board flash runner configuration (if it exists) and store  | 
224 | 239 |             # single-use commands in a dictionary so that they get executed  | 
225 | 240 |             # once per unique board name.  | 
226 |  | -            if cache['BOARD_DIR'] not in processed_boards and 'SOC_FULL_DIR' in cache:  | 
227 |  | -                soc_yaml_file = Path(cache['SOC_FULL_DIR']) / 'soc.yml'  | 
228 |  | -                board_yaml_file = Path(cache['BOARD_DIR']) / 'board.yml'  | 
229 |  | -                group_type = 'boards'  | 
230 |  | - | 
231 |  | -                # Search for flash runner configuration, board takes priority over SoC  | 
232 |  | -                try:  | 
233 |  | -                    with open(board_yaml_file, 'r') as f:  | 
234 |  | -                        data_yaml = yaml.safe_load(f.read())  | 
235 |  | - | 
236 |  | -                except FileNotFoundError:  | 
237 |  | -                    continue  | 
238 |  | - | 
239 |  | -                if 'runners' not in data_yaml:  | 
240 |  | -                    # Check SoC file  | 
241 |  | -                    group_type = 'qualifiers'  | 
242 |  | -                    try:  | 
243 |  | -                        with open(soc_yaml_file, 'r') as f:  | 
244 |  | -                            data_yaml = yaml.safe_load(f.read())  | 
245 |  | - | 
246 |  | -                    except FileNotFoundError:  | 
 | 241 | +            for directory in cache.get_list('SOC_DIRECTORIES'):  | 
 | 242 | +                if directory not in processed_boards:  | 
 | 243 | +                    check_files.append(SocBoardFilesProcessing(Path(directory) / 'soc.yml'))  | 
 | 244 | +                    processed_boards.add(directory)  | 
 | 245 | + | 
 | 246 | +            for directory in cache.get_list('BOARD_DIRECTORIES'):  | 
 | 247 | +                if directory not in processed_boards:  | 
 | 248 | +                    check_files.append(SocBoardFilesProcessing(Path(directory) / 'board.yml', True))  | 
 | 249 | +                    processed_boards.add(directory)  | 
 | 250 | + | 
 | 251 | +        for check in check_files:  | 
 | 252 | +            try:  | 
 | 253 | +                with open(check.filename, 'r') as f:  | 
 | 254 | +                    check.yaml = yaml.safe_load(f.read())  | 
 | 255 | + | 
 | 256 | +                    if 'runners' not in check.yaml:  | 
 | 257 | +                        continue  | 
 | 258 | +                    elif check.board is False and 'run_once' not in check.yaml['runners']:  | 
247 | 259 |                         continue  | 
248 | 260 | 
 
  | 
249 |  | -                processed_boards.add(cache['BOARD_DIR'])  | 
250 |  | - | 
251 |  | -                if 'runners' not in data_yaml or 'run_once' not in data_yaml['runners']:  | 
252 |  | -                    continue  | 
253 |  | - | 
254 |  | -                for cmd in data_yaml['runners']['run_once']:  | 
255 |  | -                    for data in data_yaml['runners']['run_once'][cmd]:  | 
256 |  | -                        for group in data['groups']:  | 
257 |  | -                            run_first = bool(data['run'] == 'first')  | 
258 |  | -                            if group_type == 'qualifiers':  | 
259 |  | -                                targets = []  | 
260 |  | -                                for target in group[group_type]:  | 
261 |  | -                                    # For SoC-based qualifiers, prepend to the beginning of the  | 
262 |  | -                                    # match to allow for matching any board name  | 
263 |  | -                                    targets.append('([^/]+)/' + target)  | 
264 |  | -                            else:  | 
265 |  | -                                targets = group[group_type]  | 
266 |  | - | 
267 |  | -                            used_cmds.append(UsedFlashCommand(cmd, targets, data['runners'], run_first))  | 
 | 261 | +                    if 'priority' in check.yaml['runners']:  | 
 | 262 | +                        check.priority = check.yaml['runners']['priority']  | 
 | 263 | +                    else:  | 
 | 264 | +                        check.priority = BOARD_FILE_RUN_ONCE_DEFAULT_PRIORITY if check.board is True else SOC_FILE_RUN_ONCE_DEFAULT_PRIORITY  | 
 | 265 | + | 
 | 266 | +                    if check.priority == highest_priority:  | 
 | 267 | +                        log.die("Duplicate flash run once configuration found with equal priorities")  | 
 | 268 | + | 
 | 269 | +                    elif check.priority > highest_priority:  | 
 | 270 | +                        highest_priority = check.priority  | 
 | 271 | +                        highest_entry = check  | 
 | 272 | + | 
 | 273 | +            except FileNotFoundError:  | 
 | 274 | +                continue  | 
 | 275 | + | 
 | 276 | +        if highest_entry is not None:  | 
 | 277 | +            group_type = 'boards' if highest_entry.board is True else 'qualifiers'  | 
 | 278 | + | 
 | 279 | +            for cmd in highest_entry.yaml['runners']['run_once']:  | 
 | 280 | +                for data in highest_entry.yaml['runners']['run_once'][cmd]:  | 
 | 281 | +                    for group in data['groups']:  | 
 | 282 | +                        run_first = bool(data['run'] == 'first')  | 
 | 283 | +                        if group_type == 'qualifiers':  | 
 | 284 | +                            targets = []  | 
 | 285 | +                            for target in group[group_type]:  | 
 | 286 | +                                # For SoC-based qualifiers, prepend to the beginning of the  | 
 | 287 | +                                # match to allow for matching any board name  | 
 | 288 | +                                targets.append('([^/]+)/' + target)  | 
 | 289 | +                        else:  | 
 | 290 | +                            targets = group[group_type]  | 
 | 291 | + | 
 | 292 | +                        used_cmds.append(UsedFlashCommand(cmd, targets, data['runners'], run_first))  | 
268 | 293 | 
 
  | 
269 | 294 |     # Reduce entries to only those having matching board names (either exact or with regex) and  | 
270 | 295 |     # remove any entries with empty board lists  | 
 | 
0 commit comments