@@ -255,6 +255,50 @@ def main() -> None:
255
255
type = lambda s : int (s , 0 ),
256
256
help = "Absolute flash address of the UICR region (decimal or 0x-prefixed hex)" ,
257
257
)
258
+ parser .add_argument (
259
+ "--secondary" ,
260
+ action = "store_true" ,
261
+ help = "Enable secondary firmware support in UICR" ,
262
+ )
263
+ parser .add_argument (
264
+ "--secondary-address" ,
265
+ default = None ,
266
+ type = lambda s : int (s , 0 ),
267
+ help = "Absolute flash address of the secondary firmware (decimal or 0x-prefixed hex)" ,
268
+ )
269
+ parser .add_argument (
270
+ "--secondary-periphconf-address" ,
271
+ default = None ,
272
+ type = lambda s : int (s , 0 ),
273
+ help = (
274
+ "Absolute flash address of the secondary PERIPHCONF partition "
275
+ "(decimal or 0x-prefixed hex)"
276
+ ),
277
+ )
278
+ parser .add_argument (
279
+ "--secondary-periphconf-size" ,
280
+ default = None ,
281
+ type = lambda s : int (s , 0 ),
282
+ help = "Size in bytes of the secondary PERIPHCONF partition (decimal or 0x-prefixed hex)" ,
283
+ )
284
+ parser .add_argument (
285
+ "--in-secondary-periphconf-elf" ,
286
+ dest = "in_secondary_periphconf_elfs" ,
287
+ default = [],
288
+ action = "append" ,
289
+ type = argparse .FileType ("rb" ),
290
+ help = (
291
+ "Path to an ELF file to extract secondary PERIPHCONF data from. "
292
+ "Can be provided multiple times. The secondary PERIPHCONF data from each ELF file "
293
+ "is combined in a single list which is sorted by ascending address and cleared "
294
+ "of duplicate entries."
295
+ ),
296
+ )
297
+ parser .add_argument (
298
+ "--out-secondary-periphconf-hex" ,
299
+ type = argparse .FileType ("w" , encoding = "utf-8" ),
300
+ help = "Path to write the secondary PERIPHCONF-only HEX file to" ,
301
+ )
258
302
args = parser .parse_args ()
259
303
260
304
try :
@@ -267,6 +311,22 @@ def main() -> None:
267
311
if args .periphconf_size is None :
268
312
raise ScriptError ("--periphconf-size is required when --out-periphconf-hex is used" )
269
313
314
+ # Validate secondary argument dependencies
315
+ if args .secondary and args .secondary_address is None :
316
+ raise ScriptError ("--secondary-address is required when --secondary is used" )
317
+
318
+ if args .out_secondary_periphconf_hex :
319
+ if args .secondary_periphconf_address is None :
320
+ raise ScriptError (
321
+ "--secondary-periphconf-address is required when "
322
+ "--out-secondary-periphconf-hex is used"
323
+ )
324
+ if args .secondary_periphconf_size is None :
325
+ raise ScriptError (
326
+ "--secondary-periphconf-size is required when "
327
+ "--out-secondary-periphconf-hex is used"
328
+ )
329
+
270
330
init_values = DISABLED_VALUE .to_bytes (4 , "little" ) * (c .sizeof (Uicr ) // 4 )
271
331
uicr = Uicr .from_buffer_copy (init_values )
272
332
@@ -275,6 +335,7 @@ def main() -> None:
275
335
276
336
# Process periphconf data first and configure UICR completely before creating hex objects
277
337
periphconf_hex = IntelHex ()
338
+ secondary_periphconf_hex = IntelHex ()
278
339
279
340
if args .out_periphconf_hex :
280
341
periphconf_combined = extract_and_combine_periphconfs (args .in_periphconf_elfs )
@@ -301,6 +362,44 @@ def main() -> None:
301
362
302
363
uicr .PERIPHCONF .MAXCOUNT = args .periphconf_size // 8
303
364
365
+ # Handle secondary firmware configuration
366
+ if args .secondary :
367
+ uicr .SECONDARY .ENABLE = ENABLED_VALUE
368
+ uicr .SECONDARY .ADDRESS = args .secondary_address
369
+
370
+ # Handle secondary periphconf if provided
371
+ if args .out_secondary_periphconf_hex :
372
+ secondary_periphconf_combined = extract_and_combine_periphconfs (
373
+ args .in_secondary_periphconf_elfs
374
+ )
375
+
376
+ padding_len = args .secondary_periphconf_size - len (secondary_periphconf_combined )
377
+ secondary_periphconf_final = secondary_periphconf_combined + bytes (
378
+ [0xFF for _ in range (padding_len )]
379
+ )
380
+
381
+ # Add secondary periphconf data to secondary periphconf hex object
382
+ secondary_periphconf_hex .frombytes (
383
+ secondary_periphconf_final , offset = args .secondary_periphconf_address
384
+ )
385
+
386
+ # Configure UICR with secondary periphconf settings
387
+ uicr .SECONDARY .PERIPHCONF .ENABLE = ENABLED_VALUE
388
+ uicr .SECONDARY .PERIPHCONF .ADDRESS = args .secondary_periphconf_address
389
+
390
+ # MAXCOUNT is given in number of 8-byte peripheral
391
+ # configuration entries and secondary_periphconf_size is given in
392
+ # bytes. When setting MAXCOUNT based on the
393
+ # secondary_periphconf_size we must first assert that
394
+ # secondary_periphconf_size has not been misconfigured.
395
+ if args .secondary_periphconf_size % 8 != 0 :
396
+ raise ScriptError (
397
+ f"args.secondary_periphconf_size was { args .secondary_periphconf_size } , "
398
+ f"but must be divisible by 8"
399
+ )
400
+
401
+ uicr .SECONDARY .PERIPHCONF .MAXCOUNT = args .secondary_periphconf_size // 8
402
+
304
403
# Create UICR hex object with final UICR data
305
404
uicr_hex = IntelHex ()
306
405
uicr_hex .frombytes (bytes (uicr ), offset = args .uicr_address )
@@ -311,9 +410,12 @@ def main() -> None:
311
410
312
411
if args .out_periphconf_hex :
313
412
periphconf_hex .write_hex_file (args .out_periphconf_hex )
314
-
315
413
merged_hex .fromdict (periphconf_hex .todict ())
316
414
415
+ if args .out_secondary_periphconf_hex :
416
+ secondary_periphconf_hex .write_hex_file (args .out_secondary_periphconf_hex )
417
+ merged_hex .fromdict (secondary_periphconf_hex .todict ())
418
+
317
419
merged_hex .write_hex_file (args .out_merged_hex )
318
420
uicr_hex .write_hex_file (args .out_uicr_hex )
319
421
0 commit comments