@@ -255,6 +255,50 @@ def main() -> None:
255255 type = lambda s : int (s , 0 ),
256256 help = "Absolute flash address of the UICR region (decimal or 0x-prefixed hex)" ,
257257 )
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+ )
258302 args = parser .parse_args ()
259303
260304 try :
@@ -267,6 +311,22 @@ def main() -> None:
267311 if args .periphconf_size is None :
268312 raise ScriptError ("--periphconf-size is required when --out-periphconf-hex is used" )
269313
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+
270330 init_values = DISABLED_VALUE .to_bytes (4 , "little" ) * (c .sizeof (Uicr ) // 4 )
271331 uicr = Uicr .from_buffer_copy (init_values )
272332
@@ -275,6 +335,7 @@ def main() -> None:
275335
276336 # Process periphconf data first and configure UICR completely before creating hex objects
277337 periphconf_hex = IntelHex ()
338+ secondary_periphconf_hex = IntelHex ()
278339
279340 if args .out_periphconf_hex :
280341 periphconf_combined = extract_and_combine_periphconfs (args .in_periphconf_elfs )
@@ -301,6 +362,44 @@ def main() -> None:
301362
302363 uicr .PERIPHCONF .MAXCOUNT = args .periphconf_size // 8
303364
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+
304403 # Create UICR hex object with final UICR data
305404 uicr_hex = IntelHex ()
306405 uicr_hex .frombytes (bytes (uicr ), offset = args .uicr_address )
@@ -311,9 +410,12 @@ def main() -> None:
311410
312411 if args .out_periphconf_hex :
313412 periphconf_hex .write_hex_file (args .out_periphconf_hex )
314-
315413 merged_hex .fromdict (periphconf_hex .todict ())
316414
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+
317419 merged_hex .write_hex_file (args .out_merged_hex )
318420 uicr_hex .write_hex_file (args .out_uicr_hex )
319421
0 commit comments