Skip to content

Commit d14185f

Browse files
committed
[nrf fromlist] soc: nordic: gen_uicr: Support secondary firmware
Add support for secondary firmware in gen_uicr.py. Upstream PR #: 95410 Signed-off-by: Sebastian Bøe <[email protected]>
1 parent 17efa59 commit d14185f

File tree

5 files changed

+166
-8
lines changed

5 files changed

+166
-8
lines changed

boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,5 +166,13 @@
166166
periphconf_partition: partition@1ae000 {
167167
reg = <0x1ae000 DT_SIZE_K(8)>;
168168
};
169+
170+
secondary_partition: partition@1b0000 {
171+
reg = <0x1b0000 DT_SIZE_K(64)>;
172+
};
173+
174+
secondary_periphconf_partition: partition@1c0000 {
175+
reg = <0x1c2000 DT_SIZE_K(8)>;
176+
};
169177
};
170178
};

scripts/ci/check_compliance.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,8 @@ def check_no_undef_outside_kconfig(self, kconf):
12261226
"FOO_SETTING_1",
12271227
"FOO_SETTING_2",
12281228
"GEN_UICR_GENERATE_PERIPHCONF", # Used in specialized build tool, not part of main Kconfig
1229+
"GEN_UICR_SECONDARY", # Used in specialized build tool, not part of main Kconfig
1230+
"GEN_UICR_SECONDARY_GENERATE_PERIPHCONF", # Used in specialized build tool, not part of main Kconfig
12291231
"HEAP_MEM_POOL_ADD_SIZE_", # Used as an option matching prefix
12301232
"HUGETLBFS", # Linux, in boards/xtensa/intel_adsp_cavs25/doc
12311233
"IAR_BUFFERED_WRITE",

soc/nordic/common/uicr/gen_uicr.py

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

soc/nordic/common/uicr/gen_uicr/CMakeLists.txt

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@ endif()
5151
set(periphconf_args)
5252
set(periphconf_elfs)
5353
set(merged_hex_file ${APPLICATION_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.hex)
54+
set(secondary_periphconf_elfs)
5455
set(uicr_hex_file ${APPLICATION_BINARY_DIR}/zephyr/uicr.hex)
5556
set(periphconf_hex_file ${APPLICATION_BINARY_DIR}/zephyr/periphconf.hex)
57+
set(secondary_periphconf_hex_file ${APPLICATION_BINARY_DIR}/zephyr/secondary_periphconf.hex)
5658

5759
# Get UICR absolute address from this image's devicetree
5860
dt_nodelabel(uicr_path NODELABEL "uicr" REQUIRED)
@@ -75,7 +77,14 @@ if(CONFIG_GEN_UICR_GENERATE_PERIPHCONF)
7577
if(EXISTS ${_dir}/zephyr/zephyr.dts)
7678
# Read CONFIG_KERNEL_BIN_NAME from the sibling's .config file
7779
parse_kconfig_value(${_dir}/zephyr/.config CONFIG_KERNEL_BIN_NAME kernel_bin_name)
78-
list(APPEND periphconf_elfs ${_dir}/zephyr/${kernel_bin_name}.elf)
80+
set(kernel_elf_path ${_dir}/zephyr/${kernel_bin_name}.elf)
81+
82+
# Check if this is secondary firmware by looking for the marker file
83+
if(EXISTS ${_dir}/is_secondary_firmware.txt)
84+
list(APPEND secondary_periphconf_elfs ${kernel_elf_path})
85+
else()
86+
list(APPEND periphconf_elfs ${kernel_elf_path})
87+
endif()
7988
endif()
8089
endforeach()
8190

@@ -92,21 +101,46 @@ if(CONFIG_GEN_UICR_GENERATE_PERIPHCONF)
92101
endforeach()
93102
endif(CONFIG_GEN_UICR_GENERATE_PERIPHCONF)
94103

95-
# Generate hex files (merged, uicr-only, and periphconf-only)
104+
if(CONFIG_GEN_UICR_SECONDARY)
105+
set(secondary_args --secondary)
106+
107+
# Compute SECONDARY partition absolute address from this image's devicetree
108+
compute_partition_address_and_size("secondary_partition" SECONDARY_ADDRESS SECONDARY_SIZE)
109+
110+
list(APPEND secondary_args
111+
--secondary-address ${SECONDARY_ADDRESS}
112+
)
113+
114+
if(CONFIG_GEN_UICR_SECONDARY_GENERATE_PERIPHCONF)
115+
# Compute SECONDARY_PERIPHCONF absolute address and size from this image's devicetree
116+
compute_partition_address_and_size("secondary_periphconf_partition" SECONDARY_PERIPHCONF_ADDRESS SECONDARY_PERIPHCONF_SIZE)
117+
118+
list(APPEND secondary_args --secondary-periphconf-address ${SECONDARY_PERIPHCONF_ADDRESS})
119+
list(APPEND secondary_args --secondary-periphconf-size ${SECONDARY_PERIPHCONF_SIZE})
120+
list(APPEND secondary_args --out-secondary-periphconf-hex ${secondary_periphconf_hex_file})
121+
122+
foreach(elf ${secondary_periphconf_elfs})
123+
list(APPEND secondary_args --in-secondary-periphconf-elf ${elf})
124+
endforeach()
125+
endif()
126+
endif()
127+
128+
# Generate hex files (merged, uicr-only, periphconf-only, and secondary-periphconf-only)
96129
add_custom_command(
97-
OUTPUT ${merged_hex_file} ${uicr_hex_file} ${periphconf_hex_file}
130+
OUTPUT ${merged_hex_file} ${uicr_hex_file} ${periphconf_hex_file} ${secondary_periphconf_hex_file}
98131
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${ZEPHYR_BASE}/scripts/dts/python-devicetree/src
99132
${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/soc/nordic/common/uicr/gen_uicr.py
100133
--uicr-address ${UICR_ADDRESS}
101134
--out-merged-hex ${merged_hex_file}
102135
--out-uicr-hex ${uicr_hex_file}
103136
${periphconf_args}
104-
DEPENDS ${periphconf_elfs}
137+
${secondary_args}
138+
DEPENDS ${periphconf_elfs} ${secondary_periphconf_elfs}
105139
WORKING_DIRECTORY ${APPLICATION_BINARY_DIR}
106-
COMMENT "Using gen_uicr.py to generate ${merged_hex_file} from ${periphconf_elfs}"
140+
COMMENT "Using gen_uicr.py to generate ${merged_hex_file}, ${uicr_hex_file}, ${periphconf_hex_file}, and ${secondary_periphconf_hex_file} from ${periphconf_elfs} ${secondary_periphconf_elfs}"
107141
)
108142

109143
# Add zephyr subdirectory to handle flash configuration with correct paths
110144
add_subdirectory(zephyr)
111145

112-
add_custom_target(gen_uicr ALL DEPENDS ${merged_hex_file})
146+
add_custom_target(gen_uicr ALL DEPENDS ${merged_hex_file} ${uicr_hex_file} ${periphconf_hex_file} ${secondary_periphconf_hex_file})

soc/nordic/common/uicr/gen_uicr/Kconfig

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,19 @@ config GEN_UICR_GENERATE_PERIPHCONF
77
bool "Generate PERIPHCONF hex alongside UICR"
88
default y
99
help
10-
When enabled, the UICR generator will emit periphconf.hex in addition to uicr.hex.
10+
When enabled, the UICR generator will populate the
11+
periphconf_partition partition.
12+
13+
config GEN_UICR_SECONDARY
14+
bool "Enable UICR.SECONDARY.ENABLE"
15+
16+
config GEN_UICR_SECONDARY_GENERATE_PERIPHCONF
17+
bool "Generate SECONDARY.PERIPHCONF hex alongside UICR"
18+
default y
19+
depends on GEN_UICR_SECONDARY
20+
help
21+
When enabled, the UICR generator will populate the
22+
secondary_periphconf_partition partition.
1123

1224
endmenu
1325

0 commit comments

Comments
 (0)