88import argparse
99import ctypes as c
1010import math
11- import pickle
12- import re
1311import sys
14- from collections import defaultdict
1512from itertools import groupby
1613
1714from elftools .elf .elffile import ELFFile
2522# Must match the name used in the linker script.
2623PERIPHCONF_SECTION = "uicr_periphconf_entry"
2724
28- # Expected nodelabel of the UICR devicetree node, used to extract its location from the devicetree.
29- UICR_NODELABEL = "uicr"
30- # Nodelabel of the PERIPHCONF devicetree node, used to extract its location from the devicetree.
31- PERIPHCONF_NODELABEL = "periphconf_partition"
32-
3325# Common values for representing enabled/disabled in the UICR format.
3426ENABLED_VALUE = 0xFFFF_FFFF
3527DISABLED_VALUE = 0xBD23_28A8
@@ -141,18 +133,6 @@ def main() -> None:
141133 "peripherals, and to protect the device in various ways."
142134 ),
143135 )
144- parser .add_argument (
145- "--in-config" ,
146- required = True ,
147- type = argparse .FileType ("r" ),
148- help = "Path to the .config file from the application build" ,
149- )
150- parser .add_argument (
151- "--in-edt-pickle" ,
152- required = True ,
153- type = argparse .FileType ("rb" ),
154- help = "Path to the edt.pickle file from the application build" ,
155- )
156136 parser .add_argument (
157137 "--in-periphconf-elf" ,
158138 dest = "in_periphconf_elfs" ,
@@ -169,13 +149,25 @@ def main() -> None:
169149 "--out-uicr-hex" ,
170150 required = True ,
171151 type = argparse .FileType ("w" , encoding = "utf-8" ),
172- help = "Path to write the generated UICR HEX file to" ,
152+ help = "Path to write the generated merged UICR+PERIPHCONF HEX file to (typically zephyr.hex) " ,
173153 )
174154 parser .add_argument (
175- "--out- periphconf-hex " ,
155+ "--periphconf-address " ,
176156 default = None ,
177- type = argparse .FileType ("w" , encoding = "utf-8" ),
178- help = "Path to write the generated PERIPHCONF HEX file to" ,
157+ type = lambda s : int (s , 0 ),
158+ help = "Absolute flash address of the PERIPHCONF partition (decimal or 0x-prefixed hex)" ,
159+ )
160+ parser .add_argument (
161+ "--periphconf-size" ,
162+ default = None ,
163+ type = lambda s : int (s , 0 ),
164+ help = "Size in bytes of the PERIPHCONF partition (decimal or 0x-prefixed hex)" ,
165+ )
166+ parser .add_argument (
167+ "--uicr-address" ,
168+ required = True ,
169+ type = lambda s : int (s , 0 ),
170+ help = "Absolute flash address of the UICR region (decimal or 0x-prefixed hex)" ,
179171 )
180172 args = parser .parse_args ()
181173
@@ -186,49 +178,27 @@ def main() -> None:
186178 uicr .VERSION .MAJOR = UICR_FORMAT_VERSION_MAJOR
187179 uicr .VERSION .MINOR = UICR_FORMAT_VERSION_MINOR
188180
189- kconfig_str = args .in_config .read ()
190- kconfig = parse_kconfig (kconfig_str )
191-
192- edt = pickle .load (args .in_edt_pickle )
181+ # Create a single hex object that will contain both UICR and periphconf data
182+ merged_hex = IntelHex ()
193183
194- try :
195- periphconf_partition = edt .label2node [PERIPHCONF_NODELABEL ]
196- except LookupError as e :
197- raise ScriptError (
198- "Failed to find a PERIPHCONF partition in the devicetree. "
199- f"Expected a DT node with label '{ PERIPHCONF_NODELABEL } '."
200- ) from e
184+ if args .in_periphconf_elfs : # Check if periphconf data is provided
185+ periphconf_combined = extract_and_combine_periphconfs (args .in_periphconf_elfs )
201186
202- flash_base_address = periphconf_partition .flash_controller .regs [0 ].addr
203- periphconf_address = flash_base_address + periphconf_partition .regs [0 ].addr
204- periphconf_size = periphconf_partition .regs [0 ].size
187+ padding_len = args .periphconf_size - len (periphconf_combined )
188+ periphconf_final = periphconf_combined + bytes ([0xFF for _ in range (padding_len )])
205189
206- periphconf_combined = extract_and_combine_periphconfs (args .in_periphconf_elfs )
207- padding_len = periphconf_size - len (periphconf_combined )
208- periphconf_final = periphconf_combined + bytes ([0xFF for _ in range (padding_len )])
190+ # Add periphconf data to the merged hex
191+ merged_hex .frombytes (periphconf_final , offset = args .periphconf_address )
209192
210- if kconfig .get ("CONFIG_NRF_HALTIUM_UICR_PERIPHCONF" ) == "y" :
211193 uicr .PERIPHCONF .ENABLE = ENABLED_VALUE
212- uicr .PERIPHCONF .ADDRESS = periphconf_address
213- uicr .PERIPHCONF .MAXCOUNT = math .floor (periphconf_size / 8 )
214-
215- try :
216- uicr_node = edt .label2node [UICR_NODELABEL ]
217- except LookupError as e :
218- raise ScriptError (
219- "Failed to find UICR node in the devicetree. "
220- f"Expected a DT node with label '{ UICR_NODELABEL } '."
221- ) from e
194+ uicr .PERIPHCONF .ADDRESS = args .periphconf_address
195+ uicr .PERIPHCONF .MAXCOUNT = math .floor (args .periphconf_size / 8 )
222196
223- uicr_hex = IntelHex ()
224- uicr_hex .frombytes (bytes (uicr ), offset = uicr_node . regs [ 0 ]. addr )
197+ # Add UICR data to the merged hex
198+ merged_hex .frombytes (bytes (uicr ), offset = args . uicr_address )
225199
226- uicr_hex .write_hex_file (args .out_uicr_hex )
227-
228- if args .out_periphconf_hex is not None :
229- periphconf_hex = IntelHex ()
230- periphconf_hex .frombytes (periphconf_final , offset = periphconf_address )
231- periphconf_hex .write_hex_file (args .out_periphconf_hex )
200+ # Write the merged hex file containing both UICR and periphconf data
201+ merged_hex .write_hex_file (args .out_uicr_hex )
232202
233203 except ScriptError as e :
234204 print (f"Error: { e !s} " )
@@ -270,16 +240,5 @@ def extract_and_combine_periphconfs(elf_files: list[argparse.FileType]) -> bytes
270240 return bytes (final_periphconf )
271241
272242
273- def parse_kconfig (content : str ) -> dict [str , str | None ]:
274- result = defaultdict (None )
275- match_iter = re .finditer (
276- r"^(?P<config>(SB_)?CONFIG_[^=\s]+)=(?P<value>[^\s#])+$" , content , re .MULTILINE
277- )
278- for match in match_iter :
279- result [match ["config" ]] = match ["value" ]
280-
281- return result
282-
283-
284243if __name__ == "__main__" :
285244 main ()
0 commit comments