@@ -255,6 +255,46 @@ 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 = "Absolute flash address of the secondary PERIPHCONF partition (decimal or 0x-prefixed hex)" ,
274+ )
275+ parser .add_argument (
276+ "--secondary-periphconf-size" ,
277+ default = None ,
278+ type = lambda s : int (s , 0 ),
279+ help = "Size in bytes of the secondary PERIPHCONF partition (decimal or 0x-prefixed hex)" ,
280+ )
281+ parser .add_argument (
282+ "--in-secondary-periphconf-elf" ,
283+ dest = "in_secondary_periphconf_elfs" ,
284+ default = [],
285+ action = "append" ,
286+ type = argparse .FileType ("rb" ),
287+ help = (
288+ "Path to an ELF file to extract secondary PERIPHCONF data from. Can be provided multiple times. "
289+ "The secondary PERIPHCONF data from each ELF file is combined in a single list which is sorted "
290+ "by ascending address and cleared of duplicate entries."
291+ ),
292+ )
293+ parser .add_argument (
294+ "--out-secondary-periphconf-hex" ,
295+ type = argparse .FileType ("w" , encoding = "utf-8" ),
296+ help = "Path to write the secondary PERIPHCONF-only HEX file to" ,
297+ )
258298 args = parser .parse_args ()
259299
260300 try :
@@ -267,6 +307,21 @@ def main() -> None:
267307 if args .periphconf_size is None :
268308 raise ScriptError ("--periphconf-size is required when --out-periphconf-hex is used" )
269309
310+ # Validate secondary argument dependencies
311+ if args .secondary :
312+ if args .secondary_address is None :
313+ raise ScriptError ("--secondary-address is required when --secondary is used" )
314+
315+ if args .out_secondary_periphconf_hex :
316+ if args .secondary_periphconf_address is None :
317+ raise ScriptError (
318+ "--secondary-periphconf-address is required when --out-secondary-periphconf-hex is used"
319+ )
320+ if args .secondary_periphconf_size is None :
321+ raise ScriptError (
322+ "--secondary-periphconf-size is required when --out-secondary-periphconf-hex is used"
323+ )
324+
270325 init_values = DISABLED_VALUE .to_bytes (4 , "little" ) * (c .sizeof (Uicr ) // 4 )
271326 uicr = Uicr .from_buffer_copy (init_values )
272327
@@ -275,6 +330,7 @@ def main() -> None:
275330
276331 # Process periphconf data first and configure UICR completely before creating hex objects
277332 periphconf_hex = IntelHex ()
333+ secondary_periphconf_hex = IntelHex ()
278334
279335 if args .out_periphconf_hex :
280336 periphconf_combined = extract_and_combine_periphconfs (args .in_periphconf_elfs )
@@ -301,6 +357,37 @@ def main() -> None:
301357
302358 uicr .PERIPHCONF .MAXCOUNT = args .periphconf_size // 8
303359
360+ # Handle secondary firmware configuration
361+ if args .secondary :
362+ uicr .SECONDARY .ENABLE = ENABLED_VALUE
363+ uicr .SECONDARY .ADDRESS = args .secondary_address
364+
365+ # Handle secondary periphconf if provided
366+ if args .out_secondary_periphconf_hex :
367+ secondary_periphconf_combined = extract_and_combine_periphconfs (args .in_secondary_periphconf_elfs )
368+
369+ padding_len = args .secondary_periphconf_size - len (secondary_periphconf_combined )
370+ secondary_periphconf_final = secondary_periphconf_combined + bytes ([0xFF for _ in range (padding_len )])
371+
372+ # Add secondary periphconf data to secondary periphconf hex object
373+ secondary_periphconf_hex .frombytes (secondary_periphconf_final , offset = args .secondary_periphconf_address )
374+
375+ # Configure UICR with secondary periphconf settings
376+ uicr .SECONDARY .PERIPHCONF .ENABLE = ENABLED_VALUE
377+ uicr .SECONDARY .PERIPHCONF .ADDRESS = args .secondary_periphconf_address
378+
379+ # MAXCOUNT is given in number of 8-byte peripheral
380+ # configuration entries and secondary_periphconf_size is given in
381+ # bytes. When setting MAXCOUNT based on the
382+ # secondary_periphconf_size we must first assert that
383+ # secondary_periphconf_size has not been misconfigured.
384+ if args .secondary_periphconf_size % 8 != 0 :
385+ raise ScriptError (
386+ f"args.secondary_periphconf_size was { args .secondary_periphconf_size } , but must be divisible by 8"
387+ )
388+
389+ uicr .SECONDARY .PERIPHCONF .MAXCOUNT = args .secondary_periphconf_size // 8
390+
304391 # Create UICR hex object with final UICR data
305392 uicr_hex = IntelHex ()
306393 uicr_hex .frombytes (bytes (uicr ), offset = args .uicr_address )
@@ -311,9 +398,12 @@ def main() -> None:
311398
312399 if args .out_periphconf_hex :
313400 periphconf_hex .write_hex_file (args .out_periphconf_hex )
314-
315401 merged_hex .fromdict (periphconf_hex .todict ())
316402
403+ if args .out_secondary_periphconf_hex :
404+ secondary_periphconf_hex .write_hex_file (args .out_secondary_periphconf_hex )
405+ merged_hex .fromdict (secondary_periphconf_hex .todict ())
406+
317407 merged_hex .write_hex_file (args .out_merged_hex )
318408 uicr_hex .write_hex_file (args .out_uicr_hex )
319409
0 commit comments