Skip to content

Commit f222be7

Browse files
committed
Simplify the nucleo-n657x0-q package derivation
Signed-off-by: Brendan Moran <brendan.moran@arm.com>
1 parent c3bae77 commit f222be7

1 file changed

Lines changed: 150 additions & 202 deletions

File tree

nix/nucleo-n657x0-q/default.nix

Lines changed: 150 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
, fetchFromGitHub
77
, writeText
88
}:
9+
# Construct a minimal STM32CubeN6-based platform environment for building
10+
# nucleo-n657x0-q benchmarks. The package copies only the required Cube headers
11+
# and sources, then patches selected files where needed to get the intended
12+
# RAM-loaded benchmark behavior.
913
stdenvNoCC.mkDerivation {
1014
pname = "mlkem-native-nucleo-n657x0-q";
1115
version = "main";
1216

13-
# Fetch STM32CubeN6 (Template + CMSIS headers)
14-
# TODO(GAP): Pin rev + hash for reproducibility.
1517
src = fetchFromGitHub {
1618
owner = "STMicroelectronics";
1719
repo = "STM32CubeN6";
@@ -22,222 +24,168 @@ stdenvNoCC.mkDerivation {
2224

2325
dontBuild = true;
2426

25-
propagatedBuildInputs = [ ];
26-
2727
installPhase = ''
2828
set -eu
2929
3030
outp="$out/platform/nucleo-n657x0-q/src/platform"
31-
mkdir -p "$outp"
32-
33-
tpl="Projects/NUCLEO-N657X0-Q/Templates/Template"
34-
35-
if [ ! -d "$tpl" ]; then
36-
echo "ERROR: expected Cube template at $tpl"
37-
exit 1
38-
fi
39-
40-
# Copy CMSIS headers needed by system/startup from the Cube tree
41-
mkdir -p "$outp/Drivers/CMSIS/Core"
42-
mkdir -p "$outp/Drivers/CMSIS/Device"
43-
44-
cp -r "Drivers/CMSIS/Core/Include" "$outp/Drivers/CMSIS/Core/"
45-
# Ensure m-profile subdir (pmu_armv8.h) is present, as some builds include it directly
46-
if [ -d "Drivers/CMSIS/Core/Include/m-profile" ]; then
47-
mkdir -p "$outp/Drivers/CMSIS/Core/Include"
48-
cp -r "Drivers/CMSIS/Core/Include/m-profile" "$outp/Drivers/CMSIS/Core/Include/" || true
49-
fi
50-
cp -r "Drivers/CMSIS/Device/ST" "$outp/Drivers/CMSIS/Device/"
51-
52-
# Copy startup + system files
53-
# Prefer board-specific FSBL-LRUN files explicitly when available.
5431
fsbl_tpl="Projects/NUCLEO-N657X0-Q/Templates/Template_FSBL_LRUN"
55-
mkdir -p "$outp/gcc"
56-
if [ -d "$fsbl_tpl" ]; then
57-
# Explicitly select:
58-
# - Startup: STM32CubeIDE/Boot/Startup/startup_stm32n657xx_fsbl.s
59-
# - System: FSBL/Src/system_stm32n6xx_fsbl.c
60-
# - IT/MSP: FSBL/Src/stm32n6xx_it.c, stm32n6xx_hal_msp.c
61-
start_src="$fsbl_tpl/STM32CubeIDE/Boot/Startup/startup_stm32n657xx_fsbl.s"
62-
sys_src="$fsbl_tpl/FSBL/Src/system_stm32n6xx_fsbl.c"
63-
it_src="$fsbl_tpl/FSBL/Src/stm32n6xx_it.c"
64-
msp_src="$fsbl_tpl/FSBL/Src/stm32n6xx_hal_msp.c"
65-
if [ -f "$start_src" ]; then
66-
# Normalize to canonical name searched by platform.mk
67-
cp -v "$start_src" "$outp/gcc/startup_stm32n657xx.S"
68-
# Replace the Cube FSBL startup's fixed SRAM initial SP with the
69-
# linker-provided stack top so RAM-only tests can use the DTCM stack
70-
# selected by their linker script.
71-
sed -i.bak -E 's@[.]word[[:space:]]+0x34110000@.word _estack@' "$outp/gcc/startup_stm32n657xx.S"
72-
# Disable interrupts immediately on entry to Reset_Handler. The RAM
73-
# test image starts after debugger-controlled load/jump, so this keeps
74-
# stale board/debug state from delivering an interrupt before C startup
75-
# has initialized the test image.
76-
sed -i.bak -E '/^Reset_Handler:/a\ cpsid i' "$outp/gcc/startup_stm32n657xx.S"
77-
fi
78-
if [ -f "$sys_src" ]; then
79-
cp -v "$sys_src" "$outp/system_stm32n6xx.c"
80-
fi
81-
if [ -f "$it_src" ]; then
82-
cp -v "$it_src" "$outp/"
83-
fi
84-
if [ -f "$msp_src" ]; then
85-
cp -v "$msp_src" "$outp/"
86-
fi
87-
else
88-
# Generic fallback to CMSIS templates if FSBL files are not located
89-
cp -r Drivers/CMSIS/Device/ST/STM32N6xx/Source/Templates/* "$outp" || true
90-
cp -r Drivers/CMSIS/Device/ST/STM32N6xx/Source/Templates/gcc/* "$outp/gcc/" || true
91-
fi
32+
hal="Drivers/STM32N6xx_HAL_Driver"
33+
cmsis_core="Drivers/CMSIS/Core/Include"
34+
cmsis_device="Drivers/CMSIS/Device/ST/STM32N6xx/Include"
35+
36+
install_file() {
37+
src_file="$1"
38+
dst_file="$outp/$2"
39+
mkdir -p "$(dirname "$dst_file")"
40+
cp "$src_file" "$dst_file"
41+
}
42+
43+
# CMSIS headers reached by stm32n657xx.h/core_cm55.h under the GCC build.
44+
for header in \
45+
cmsis_compiler.h \
46+
cmsis_gcc.h \
47+
cmsis_version.h \
48+
core_cm55.h \
49+
m-profile/armv7m_cachel1.h \
50+
m-profile/armv8m_mpu.h \
51+
m-profile/armv8m_pmu.h \
52+
m-profile/cmsis_gcc_m.h
53+
do
54+
install_file "$cmsis_core/$header" "Drivers/CMSIS/Core/Include/$header"
55+
done
56+
57+
for header in \
58+
stm32n6xx.h \
59+
stm32n657xx.h \
60+
system_stm32n6xx.h
61+
do
62+
install_file "$cmsis_device/$header" "Drivers/CMSIS/Device/ST/STM32N6xx/Include/$header"
63+
done
64+
65+
# FSBL files used by platform.mk.
66+
install_file \
67+
"$fsbl_tpl/STM32CubeIDE/Boot/Startup/startup_stm32n657xx_fsbl.s" \
68+
"gcc/startup_stm32n657xx.S"
69+
70+
# Use the linker-provided stack top instead of Cube's fixed SRAM stack.
71+
sed -i.bak -E 's@[.]word[[:space:]]+0x34110000@.word _estack@' \
72+
"$outp/gcc/startup_stm32n657xx.S"
73+
74+
# Mask interrupts as soon as Reset_Handler starts to avoid stale debug/board
75+
# state firing before this RAM-loaded test image initializes C runtime state.
76+
sed -i.bak -E '/^Reset_Handler:/a\ cpsid i' \
77+
"$outp/gcc/startup_stm32n657xx.S"
78+
rm -f "$outp/gcc/startup_stm32n657xx.S.bak"
79+
80+
install_file "$fsbl_tpl/FSBL/Src/system_stm32n6xx_fsbl.c" "system_stm32n6xx.c"
81+
install_file "$fsbl_tpl/FSBL/Src/stm32n6xx_it.c" "stm32n6xx_it.c"
82+
install_file "$fsbl_tpl/FSBL/Inc/stm32n6xx_it.h" "Inc/stm32n6xx_it.h"
83+
install_file "$fsbl_tpl/FSBL/Inc/main.h" "Inc/main.h"
84+
install_file "$fsbl_tpl/FSBL/Inc/stm32n6xx_hal_conf.h" "Inc/stm32n6xx_hal_conf.h"
9285
93-
# Copy HAL driver includes and sources so FSBL files build if they reference HAL symbols
94-
mkdir -p "$outp/Drivers/STM32N6xx_HAL_Driver"
95-
if [ -d Drivers/STM32N6xx_HAL_Driver/Inc ]; then
96-
cp -r Drivers/STM32N6xx_HAL_Driver/Inc "$outp/Drivers/STM32N6xx_HAL_Driver/" || true
97-
fi
98-
if [ -d Drivers/STM32N6xx_HAL_Driver/Src ]; then
99-
cp -r Drivers/STM32N6xx_HAL_Driver/Src "$outp/Drivers/STM32N6xx_HAL_Driver/" || true
100-
fi
101-
# Guarantee HAL Driver Src exists under output (fallback search if not found in expected path)
102-
if [ ! -d "$outp/Drivers/STM32N6xx_HAL_Driver/Src" ]; then
103-
alt_hal_dir=$(find Drivers -type d -name 'STM32N6xx_HAL_Driver' -print -quit || true)
104-
if [ -n "$alt_hal_dir" ] && [ -d "$alt_hal_dir/Src" ]; then
105-
echo "Copying HAL Driver Src from $alt_hal_dir"
106-
mkdir -p "$outp/Drivers/STM32N6xx_HAL_Driver"
107-
cp -r "$alt_hal_dir/Src" "$outp/Drivers/STM32N6xx_HAL_Driver/" || true
108-
fi
109-
fi
110-
111-
112-
# Copy HAL configuration header, preferring FSBL-LRUN Inc; then disable BSEC and XSPI modules
113-
fsbl_inc_conf="$fsbl_tpl/FSBL/Inc/stm32n6xx_hal_conf.h"
114-
if [ -f "$fsbl_inc_conf" ]; then
115-
mkdir -p "$outp/Inc"
116-
cp -v "$fsbl_inc_conf" "$outp/Inc/stm32n6xx_hal_conf.h"
117-
# Also provide FSBL interrupt header in include path if present
118-
fsbl_it_hdr="$fsbl_tpl/FSBL/Inc/stm32n6xx_it.h"
119-
if [ -f "$fsbl_it_hdr" ]; then
120-
cp -v "$fsbl_it_hdr" "$outp/Inc/stm32n6xx_it.h"
121-
fi
122-
# Also provide FSBL main.h in include path if present
123-
fsbl_main_hdr="$fsbl_tpl/FSBL/Inc/main.h"
124-
if [ -f "$fsbl_main_hdr" ]; then
125-
cp -v "$fsbl_main_hdr" "$outp/Inc/main.h"
126-
fi
127-
else
128-
# Fallback: Copy the first hal_conf found under Projects
129-
hal_conf=$(find Projects -type f -name 'stm32n6xx_hal_conf.h' | head -n1 || true)
130-
if [ -n "$hal_conf" ]; then
131-
incdir=$(dirname "$hal_conf")
132-
cp -r "$incdir" "$outp/Inc"
133-
# Attempt to locate an stm32n6xx_it.h nearby if FSBL header not used
134-
it_hdr=$(find "$(dirname "$incdir")" -name 'stm32n6xx_it.h' -type f | head -n1 || true)
135-
if [ -n "$it_hdr" ] && [ ! -f "$outp/Inc/stm32n6xx_it.h" ]; then
136-
cp -v "$it_hdr" "$outp/Inc/stm32n6xx_it.h"
137-
fi
138-
# Attempt to locate a main.h nearby if FSBL header not used
139-
main_hdr=$(find "$(dirname "$incdir")" -name 'main.h' -type f | head -n1 || true)
140-
if [ -n "$main_hdr" ] && [ ! -f "$outp/Inc/main.h" ]; then
141-
cp -v "$main_hdr" "$outp/Inc/main.h"
142-
fi
143-
fi
144-
fi
145-
146-
# Ensure BSEC and XSPI are disabled for our test build
14786
conf="$outp/Inc/stm32n6xx_hal_conf.h"
148-
if [ -f "$conf" ]; then
149-
# Comment out any explicit enable lines
150-
sed -i.bak -E 's@^\s*#\s*define\s+HAL_BSEC_MODULE_ENABLED@/* #define HAL_BSEC_MODULE_ENABLED */@' "$conf" || true
151-
sed -i.bak -E 's@^\s*#\s*define\s+HAL_XSPI_MODULE_ENABLED@/* #define HAL_XSPI_MODULE_ENABLED */@' "$conf" || true
152-
# Also handle commented-but-enabled variants
153-
sed -i.bak -E 's@^\s*//\s*#\s*define\s+HAL_BSEC_MODULE_ENABLED@/* #define HAL_BSEC_MODULE_ENABLED */@' "$conf" || true
154-
sed -i.bak -E 's@^\s*//\s*#\s*define\s+HAL_XSPI_MODULE_ENABLED@/* #define HAL_XSPI_MODULE_ENABLED */@' "$conf" || true
155-
sed -i.bak -E 's@^\s*/\*\s*#\s*define\s+HAL_BSEC_MODULE_ENABLED\s*\*/@/* #define HAL_BSEC_MODULE_ENABLED */@' "$conf" || true
156-
sed -i.bak -E 's@^\s*/\*\s*#\s*define\s+HAL_XSPI_MODULE_ENABLED\s*\*/@/* #define HAL_XSPI_MODULE_ENABLED */@' "$conf" || true
157-
# Belt-and-suspenders: append explicit undefs to override any includes afterward
158-
printf "\n#undef HAL_BSEC_MODULE_ENABLED\n#undef HAL_XSPI_MODULE_ENABLED\n" >> "$conf"
159-
fi
16087
161-
# Extract SystemClock_Config and related user clock snippets from FSBL template into a standalone clock_config.c
88+
# Disable BSEC because the platform test build does not link the BSEC HAL.
89+
sed -i.bak -E 's@^[[:space:]]*#[[:space:]]*define[[:space:]]+HAL_BSEC_MODULE_ENABLED@/* #define HAL_BSEC_MODULE_ENABLED */@' "$conf"
90+
91+
# Disable XSPI because only the extracted clock setup is used, not Cube's
92+
# external memory setup or XSPI HAL driver.
93+
sed -i.bak -E 's@^[[:space:]]*#[[:space:]]*define[[:space:]]+HAL_XSPI_MODULE_ENABLED@/* #define HAL_XSPI_MODULE_ENABLED */@' "$conf"
94+
rm -f "$conf.bak"
95+
96+
# HAL files named directly by platform.mk, plus headers enabled by the
97+
# pruned FSBL HAL config and their direct dependencies.
98+
for header in \
99+
Legacy/stm32_hal_legacy.h \
100+
stm32n6xx_hal.h \
101+
stm32n6xx_hal_cortex.h \
102+
stm32n6xx_hal_def.h \
103+
stm32n6xx_hal_dma.h \
104+
stm32n6xx_hal_dma_ex.h \
105+
stm32n6xx_hal_exti.h \
106+
stm32n6xx_hal_gpio.h \
107+
stm32n6xx_hal_gpio_ex.h \
108+
stm32n6xx_hal_pwr.h \
109+
stm32n6xx_hal_pwr_ex.h \
110+
stm32n6xx_hal_rcc.h \
111+
stm32n6xx_hal_rcc_ex.h \
112+
stm32n6xx_ll_bus.h \
113+
stm32n6xx_ll_rcc.h
114+
do
115+
install_file "$hal/Inc/$header" "Drivers/STM32N6xx_HAL_Driver/Inc/$header"
116+
done
117+
118+
for source in \
119+
stm32n6xx_hal.c \
120+
stm32n6xx_hal_cortex.c \
121+
stm32n6xx_hal_pwr.c \
122+
stm32n6xx_hal_pwr_ex.c \
123+
stm32n6xx_hal_rcc.c \
124+
stm32n6xx_hal_rcc_ex.c
125+
do
126+
install_file "$hal/Src/$source" "Drivers/STM32N6xx_HAL_Driver/Src/$source"
127+
done
128+
162129
fsbl_main_c="$fsbl_tpl/FSBL/Src/main.c"
163130
clock_out="$outp/clock_config.c"
164-
if [ -f "$fsbl_main_c" ]; then
165-
echo "Generating clock_config.c from $fsbl_main_c"
166-
tmpclk="$TMPDIR/clock_config.$$.$RANDOM.c"
167-
: > "$tmpclk"
168-
# 1) Header block
169-
awk '
170-
/\/\* USER CODE BEGIN Header \*\// { print; inhdr=1; next }
171-
inhdr { print }
172-
/\/\* USER CODE END Header \*\// { print; inhdr=0 }
173-
' "$fsbl_main_c" >> "$tmpclk"
174-
# 2) Includes lines
175-
printf "\n/* Includes ------------------------------------------------------------------*/\n" >> "$tmpclk"
176-
printf "#include \"main.h\"\n\n" >> "$tmpclk"
177-
# 3) USER CLK 1 block
178-
awk '
179-
/\/\* USER CODE BEGIN CLK 1 \*\// { print; inclk=1; next }
180-
inclk { print }
181-
/\/\* USER CODE END CLK 1 \*\// { print; inclk=0 }
182-
' "$fsbl_main_c" >> "$tmpclk"
183-
printf "\n" >> "$tmpclk"
184-
# 4) SystemClock_Config (try to include preceding comment header if present)
185-
awk '
186-
BEGIN { copy=0; lvl=0; sig=0 }
187-
# Signature with brace on same line
188-
/^[ \t]*void[ \t]+SystemClock_Config[ \t]*\([ \t]*void[ \t]*\)[ \t]*\{/ {
189-
print; copy=1; lvl=1; next
190-
}
191-
# Signature line without brace; start copying and wait for opening brace
192-
/^[ \t]*void[ \t]+SystemClock_Config[ \t]*\([ \t]*void[ \t]*\)[ \t]*$/ {
193-
print; copy=1; sig=1; next
194-
}
195-
copy {
196-
if (sig) {
197-
# Print until we see the first brace; then start level tracking
198-
if ($0 ~ /\{/) {
199-
nopen=gsub(/{/,"{"); nclose=gsub(/}/,"}"); lvl += nopen - nclose; print; sig=0;
200-
if (lvl<=0) exit; next
201-
}
202-
print; next
203-
}
204-
nopen=gsub(/{/,"{"); nclose=gsub(/}/,"}"); lvl += nopen - nclose; print;
205-
if (lvl<=0) exit
206-
}
207-
' "$fsbl_main_c" >> "$tmpclk"
208-
# Sanity check: ensure we captured the function signature
209-
if ! grep -q "SystemClock_Config" "$tmpclk"; then
210-
echo "ERROR: Failed to extract SystemClock_Config from $fsbl_main_c" >&2
211-
exit 1
212-
fi
213-
mv "$tmpclk" "$clock_out"
214-
# Ensure main.h exists and declares needed prototypes
215-
mkdir -p "$outp/Inc"
216-
fsbl_main_h="$fsbl_tpl/FSBL/Inc/main.h"
217-
dest_main_h="$outp/Inc/main.h"
218-
if [ ! -f "$dest_main_h" ] && [ -f "$fsbl_main_h" ]; then
219-
cp -v "$fsbl_main_h" "$dest_main_h"
220-
fi
221-
if [ -f "$dest_main_h" ]; then
222-
if ! grep -q "void[[:space:]]\+SystemClock_Config[[:space:]]*([[:space:]]*void[[:space:]]*)" "$dest_main_h"; then
223-
printf "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n" >> "$dest_main_h"
224-
printf "void SystemClock_Config(void);\n" >> "$dest_main_h"
225-
printf "#ifdef __cplusplus\n}\n#endif\n" >> "$dest_main_h"
226-
fi
227-
if ! grep -q "void[[:space:]]\+Error_Handler[[:space:]]*([[:space:]]*void[[:space:]]*)" "$dest_main_h"; then
228-
printf "void Error_Handler(void);\n" >> "$dest_main_h"
229-
fi
230-
fi
231-
else
232-
echo "WARNING: FSBL main.c not found at $fsbl_main_c; skipping clock_config generation" >&2
131+
tmpclk="$TMPDIR/clock_config.$$.$RANDOM.c"
132+
: > "$tmpclk"
133+
134+
# Preserve the Cube file header in the generated standalone clock source.
135+
awk '
136+
/\/\* USER CODE BEGIN Header \*\// { print; inhdr=1; next }
137+
inhdr { print }
138+
/\/\* USER CODE END Header \*\// { inhdr=0 }
139+
' "$fsbl_main_c" >> "$tmpclk"
140+
printf "\n#include \"main.h\"\n\n" >> "$tmpclk"
141+
142+
# Keep Cube's clock-tree explanatory comment next to SystemClock_Config.
143+
awk '
144+
/\/\* USER CODE BEGIN CLK 1 \*\// { print; inclk=1; next }
145+
inclk { print }
146+
/\/\* USER CODE END CLK 1 \*\// { inclk=0 }
147+
' "$fsbl_main_c" >> "$tmpclk"
148+
printf "\n" >> "$tmpclk"
149+
150+
# Extract exactly the SystemClock_Config function body from the FSBL main.c
151+
# into the generated clock_config.c, tracking braces so that file does not
152+
# pull in unused FSBL code.
153+
awk '
154+
BEGIN { copy=0; lvl=0; sig=0 }
155+
/^[ \t]*void[ \t]+SystemClock_Config[ \t]*\([ \t]*void[ \t]*\)[ \t]*\{/ {
156+
print; copy=1; lvl=1; next
157+
}
158+
/^[ \t]*void[ \t]+SystemClock_Config[ \t]*\([ \t]*void[ \t]*\)[ \t]*$/ {
159+
print; copy=1; sig=1; next
160+
}
161+
copy {
162+
if (sig && $0 !~ /\{/) { print; next }
163+
nopen=gsub(/{/,"{")
164+
nclose=gsub(/}/,"}")
165+
lvl += nopen - nclose
166+
print
167+
sig=0
168+
if (lvl<=0) exit
169+
}
170+
' "$fsbl_main_c" >> "$tmpclk"
171+
grep -q "SystemClock_Config" "$tmpclk"
172+
mv "$tmpclk" "$clock_out"
173+
174+
# The standalone clock_config.c calls SystemClock_Config, so make sure the
175+
# copied FSBL main.h exposes the declaration expected by local platform code.
176+
if ! grep -q "void[[:space:]]\+SystemClock_Config[[:space:]]*([[:space:]]*void[[:space:]]*)" "$outp/Inc/main.h"; then
177+
printf "\nvoid SystemClock_Config(void);\n" >> "$outp/Inc/main.h"
233178
fi
234179
235-
# The repository linker scripts define RAM-only config/test layouts explicitly.
180+
# SystemClock_Config calls Error_Handler on HAL failures; the implementation
181+
# is provided by the platform test sources, but main.h must declare it.
182+
if ! grep -q "void[[:space:]]\+Error_Handler[[:space:]]*([[:space:]]*void[[:space:]]*)" "$outp/Inc/main.h"; then
183+
printf "void Error_Handler(void);\n" >> "$outp/Inc/main.h"
184+
fi
236185
'';
237186

238187
setupHook = writeText "setup-hook.sh" ''
239188
export NUCLEO_N657X0_Q_PATH="$1/platform/nucleo-n657x0-q/src/platform/"
240-
# Platform sources only; the devshell provides the OpenOCD runtime backend.
241189
'';
242190

243191
meta = {

0 commit comments

Comments
 (0)