Skip to content

Commit b770468

Browse files
committed
Create a nucleo-n657x0-q platform
1 parent 60c7a87 commit b770468

15 files changed

Lines changed: 1268 additions & 2 deletions

File tree

flake.nix

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
export PATH=$PWD/scripts:$PATH
4848
export PROOF_DIR="$PWD/proofs/hol_light"
4949
'';
50+
5051
in
5152
{
5253
_module.args.pkgs = import inputs.nixpkgs {
@@ -90,6 +91,26 @@
9091
} ++ pkgs.lib.optionals (!pkgs.stdenv.isDarwin) [ config.packages.valgrind_varlat ];
9192
};
9293

94+
# arm-none-eabi-gcc + platform files from pqmx
95+
packages.m55-an547 = util.m55-an547;
96+
packages.avr-toolchain = util.avr-toolchain;
97+
devShells.arm-embedded = util.mkShell {
98+
packages = builtins.attrValues
99+
{
100+
inherit (config.packages) m55-an547;
101+
inherit (pkgs) gcc-arm-embedded qemu coreutils python3 git;
102+
};
103+
};
104+
packages.nucleo-n657x0-q = util.nucleo-n657x0-q;
105+
devShells.nucleo-n657x0-q = util.mkShell {
106+
packages = builtins.attrValues ({
107+
inherit (config.packages) nucleo-n657x0-q;
108+
inherit (pkgs) gcc-arm-embedded coreutils git libffi pkg-config;
109+
});
110+
};
111+
112+
113+
devShells.avr = util.mkShell (import ./nix/avr { inherit pkgs; });
93114
packages.hol_server = util.hol_server.hol_server_start;
94115
devShells.hol_light = (util.mkShell {
95116
packages = builtins.attrValues { inherit (config.packages) linters hol_light s2n_bignum hol_server; };

nix/nucleo-n657x0-q/default.nix

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
# Copyright (c) The mldsa-native project authors
2+
# Copyright (c) The mlkem-native project authors
3+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
4+
5+
{ stdenvNoCC
6+
, fetchFromGitHub
7+
, writeText
8+
}:
9+
stdenvNoCC.mkDerivation {
10+
pname = "mlkem-native-nucleo-n657x0-q";
11+
version = "main";
12+
13+
# Fetch STM32CubeN6 (Template + CMSIS headers)
14+
# TODO(GAP): Pin rev + hash for reproducibility.
15+
src = fetchFromGitHub {
16+
owner = "STMicroelectronics";
17+
repo = "STM32CubeN6";
18+
rev = "1fc803683e03b0ce78e64523441d31acd0db2829";
19+
hash = "sha256-7iD7R3A+0YAfMZqKndWBq+z5TUY37XDVxFy5HK8/5Aw=";
20+
fetchSubmodules = true;
21+
};
22+
23+
dontBuild = true;
24+
25+
propagatedBuildInputs = [ ];
26+
27+
installPhase = ''
28+
set -eu
29+
30+
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 + linker script
53+
# Prefer board-specific FSBL-LRUN files explicitly when available.
54+
fsbl_tpl="Projects/NUCLEO-N657X0-Q/Templates/Template_FSBL_LRUN"
55+
mkdir -p "$outp/gcc" "$outp/gcc/linker"
56+
if [ -d "$fsbl_tpl" ]; then
57+
# Explicitly select:
58+
# - Startup: STM32CubeIDE/Boot/Startup/startup_stm32n657xx_fsbl.s
59+
# - Linker: STM32CubeIDE/AppS/STM32N657XX_LRUN.ld
60+
# - System: FSBL/Src/system_stm32n6xx_fsbl.c
61+
# - IT/MSP: FSBL/Src/stm32n6xx_it.c, stm32n6xx_hal_msp.c
62+
start_src="$fsbl_tpl/STM32CubeIDE/Boot/Startup/startup_stm32n657xx_fsbl.s"
63+
ld_src="$fsbl_tpl/STM32CubeIDE/AppS/STM32N657XX_LRUN.ld"
64+
sys_src="$fsbl_tpl/FSBL/Src/system_stm32n6xx_fsbl.c"
65+
it_src="$fsbl_tpl/FSBL/Src/stm32n6xx_it.c"
66+
msp_src="$fsbl_tpl/FSBL/Src/stm32n6xx_hal_msp.c"
67+
if [ -f "$start_src" ]; then
68+
# Normalize to canonical name searched by platform.mk
69+
cp -v "$start_src" "$outp/gcc/startup_stm32n657xx.S"
70+
fi
71+
if [ -f "$ld_src" ]; then
72+
cp -v "$ld_src" "$outp/gcc/linker/STM32N657XX_LRUN.ld"
73+
fi
74+
if [ -f "$sys_src" ]; then
75+
cp -v "$sys_src" "$outp/system_stm32n6xx.c"
76+
fi
77+
if [ -f "$it_src" ]; then
78+
cp -v "$it_src" "$outp/"
79+
fi
80+
if [ -f "$msp_src" ]; then
81+
cp -v "$msp_src" "$outp/"
82+
fi
83+
else
84+
# Generic fallback to CMSIS templates if FSBL files are not located
85+
cp -r Drivers/CMSIS/Device/ST/STM32N6xx/Source/Templates/* "$outp" || true
86+
cp -r Drivers/CMSIS/Device/ST/STM32N6xx/Source/Templates/gcc/* "$outp/gcc/" || true
87+
fi
88+
89+
# Copy HAL driver includes and sources so FSBL files build if they reference HAL symbols
90+
mkdir -p "$outp/Drivers/STM32N6xx_HAL_Driver"
91+
if [ -d Drivers/STM32N6xx_HAL_Driver/Inc ]; then
92+
cp -r Drivers/STM32N6xx_HAL_Driver/Inc "$outp/Drivers/STM32N6xx_HAL_Driver/" || true
93+
fi
94+
if [ -d Drivers/STM32N6xx_HAL_Driver/Src ]; then
95+
cp -r Drivers/STM32N6xx_HAL_Driver/Src "$outp/Drivers/STM32N6xx_HAL_Driver/" || true
96+
fi
97+
# Guarantee HAL Driver Src exists under output (fallback search if not found in expected path)
98+
if [ ! -d "$outp/Drivers/STM32N6xx_HAL_Driver/Src" ]; then
99+
alt_hal_dir=$(find Drivers -type d -name 'STM32N6xx_HAL_Driver' -print -quit || true)
100+
if [ -n "$alt_hal_dir" ] && [ -d "$alt_hal_dir/Src" ]; then
101+
echo "Copying HAL Driver Src from $alt_hal_dir"
102+
mkdir -p "$outp/Drivers/STM32N6xx_HAL_Driver"
103+
cp -r "$alt_hal_dir/Src" "$outp/Drivers/STM32N6xx_HAL_Driver/" || true
104+
fi
105+
fi
106+
107+
108+
# Copy HAL configuration header, preferring FSBL-LRUN Inc; then disable BSEC and XSPI modules
109+
fsbl_inc_conf="$fsbl_tpl/FSBL/Inc/stm32n6xx_hal_conf.h"
110+
if [ -f "$fsbl_inc_conf" ]; then
111+
mkdir -p "$outp/Inc"
112+
cp -v "$fsbl_inc_conf" "$outp/Inc/stm32n6xx_hal_conf.h"
113+
# Also provide FSBL interrupt header in include path if present
114+
fsbl_it_hdr="$fsbl_tpl/FSBL/Inc/stm32n6xx_it.h"
115+
if [ -f "$fsbl_it_hdr" ]; then
116+
cp -v "$fsbl_it_hdr" "$outp/Inc/stm32n6xx_it.h"
117+
fi
118+
# Also provide FSBL main.h in include path if present
119+
fsbl_main_hdr="$fsbl_tpl/FSBL/Inc/main.h"
120+
if [ -f "$fsbl_main_hdr" ]; then
121+
cp -v "$fsbl_main_hdr" "$outp/Inc/main.h"
122+
fi
123+
else
124+
# Fallback: Copy the first hal_conf found under Projects
125+
hal_conf=$(find Projects -type f -name 'stm32n6xx_hal_conf.h' | head -n1 || true)
126+
if [ -n "$hal_conf" ]; then
127+
incdir=$(dirname "$hal_conf")
128+
cp -r "$incdir" "$outp/Inc"
129+
# Attempt to locate an stm32n6xx_it.h nearby if FSBL header not used
130+
it_hdr=$(find "$(dirname "$incdir")" -name 'stm32n6xx_it.h' -type f | head -n1 || true)
131+
if [ -n "$it_hdr" ] && [ ! -f "$outp/Inc/stm32n6xx_it.h" ]; then
132+
cp -v "$it_hdr" "$outp/Inc/stm32n6xx_it.h"
133+
fi
134+
# Attempt to locate a main.h nearby if FSBL header not used
135+
main_hdr=$(find "$(dirname "$incdir")" -name 'main.h' -type f | head -n1 || true)
136+
if [ -n "$main_hdr" ] && [ ! -f "$outp/Inc/main.h" ]; then
137+
cp -v "$main_hdr" "$outp/Inc/main.h"
138+
fi
139+
fi
140+
fi
141+
142+
# Ensure BSEC and XSPI are disabled for our test build
143+
conf="$outp/Inc/stm32n6xx_hal_conf.h"
144+
if [ -f "$conf" ]; then
145+
# Comment out any explicit enable lines
146+
sed -i.bak -E 's@^\s*#\s*define\s+HAL_BSEC_MODULE_ENABLED@/* #define HAL_BSEC_MODULE_ENABLED */@' "$conf" || true
147+
sed -i.bak -E 's@^\s*#\s*define\s+HAL_XSPI_MODULE_ENABLED@/* #define HAL_XSPI_MODULE_ENABLED */@' "$conf" || true
148+
# Also handle commented-but-enabled variants
149+
sed -i.bak -E 's@^\s*//\s*#\s*define\s+HAL_BSEC_MODULE_ENABLED@/* #define HAL_BSEC_MODULE_ENABLED */@' "$conf" || true
150+
sed -i.bak -E 's@^\s*//\s*#\s*define\s+HAL_XSPI_MODULE_ENABLED@/* #define HAL_XSPI_MODULE_ENABLED */@' "$conf" || true
151+
sed -i.bak -E 's@^\s*/\*\s*#\s*define\s+HAL_BSEC_MODULE_ENABLED\s*\*/@/* #define HAL_BSEC_MODULE_ENABLED */@' "$conf" || true
152+
sed -i.bak -E 's@^\s*/\*\s*#\s*define\s+HAL_XSPI_MODULE_ENABLED\s*\*/@/* #define HAL_XSPI_MODULE_ENABLED */@' "$conf" || true
153+
# Belt-and-suspenders: append explicit undefs to override any includes afterward
154+
printf "\n#undef HAL_BSEC_MODULE_ENABLED\n#undef HAL_XSPI_MODULE_ENABLED\n" >> "$conf"
155+
fi
156+
157+
# Extract SystemClock_Config and related user clock snippets from FSBL template into a standalone clock_config.c
158+
fsbl_main_c="$fsbl_tpl/FSBL/Src/main.c"
159+
clock_out="$outp/clock_config.c"
160+
if [ -f "$fsbl_main_c" ]; then
161+
echo "Generating clock_config.c from $fsbl_main_c"
162+
tmpclk="$TMPDIR/clock_config.$$.$RANDOM.c"
163+
: > "$tmpclk"
164+
# 1) Header block
165+
awk '
166+
/\/\* USER CODE BEGIN Header \*\// { print; inhdr=1; next }
167+
inhdr { print }
168+
/\/\* USER CODE END Header \*\// { print; inhdr=0 }
169+
' "$fsbl_main_c" >> "$tmpclk"
170+
# 2) Includes lines
171+
printf "\n/* Includes ------------------------------------------------------------------*/\n" >> "$tmpclk"
172+
printf "#include \"main.h\"\n\n" >> "$tmpclk"
173+
# 3) USER CLK 1 block
174+
awk '
175+
/\/\* USER CODE BEGIN CLK 1 \*\// { print; inclk=1; next }
176+
inclk { print }
177+
/\/\* USER CODE END CLK 1 \*\// { print; inclk=0 }
178+
' "$fsbl_main_c" >> "$tmpclk"
179+
printf "\n" >> "$tmpclk"
180+
# 4) SystemClock_Config (try to include preceding comment header if present)
181+
awk '
182+
BEGIN { copy=0; lvl=0; sig=0 }
183+
# Signature with brace on same line
184+
/^[ \t]*void[ \t]+SystemClock_Config[ \t]*\([ \t]*void[ \t]*\)[ \t]*\{/ {
185+
print; copy=1; lvl=1; next
186+
}
187+
# Signature line without brace; start copying and wait for opening brace
188+
/^[ \t]*void[ \t]+SystemClock_Config[ \t]*\([ \t]*void[ \t]*\)[ \t]*$/ {
189+
print; copy=1; sig=1; next
190+
}
191+
copy {
192+
if (sig) {
193+
# Print until we see the first brace; then start level tracking
194+
if ($0 ~ /\{/) {
195+
nopen=gsub(/{/,"{"); nclose=gsub(/}/,"}"); lvl += nopen - nclose; print; sig=0;
196+
if (lvl<=0) exit; next
197+
}
198+
print; next
199+
}
200+
nopen=gsub(/{/,"{"); nclose=gsub(/}/,"}"); lvl += nopen - nclose; print;
201+
if (lvl<=0) exit
202+
}
203+
' "$fsbl_main_c" >> "$tmpclk"
204+
# Sanity check: ensure we captured the function signature
205+
if ! grep -q "SystemClock_Config" "$tmpclk"; then
206+
echo "ERROR: Failed to extract SystemClock_Config from $fsbl_main_c" >&2
207+
exit 1
208+
fi
209+
mv "$tmpclk" "$clock_out"
210+
# Ensure main.h exists and declares needed prototypes
211+
mkdir -p "$outp/Inc"
212+
fsbl_main_h="$fsbl_tpl/FSBL/Inc/main.h"
213+
dest_main_h="$outp/Inc/main.h"
214+
if [ ! -f "$dest_main_h" ] && [ -f "$fsbl_main_h" ]; then
215+
cp -v "$fsbl_main_h" "$dest_main_h"
216+
fi
217+
if [ -f "$dest_main_h" ]; then
218+
if ! grep -q "void[[:space:]]\+SystemClock_Config[[:space:]]*([[:space:]]*void[[:space:]]*)" "$dest_main_h"; then
219+
printf "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n" >> "$dest_main_h"
220+
printf "void SystemClock_Config(void);\n" >> "$dest_main_h"
221+
printf "#ifdef __cplusplus\n}\n#endif\n" >> "$dest_main_h"
222+
fi
223+
if ! grep -q "void[[:space:]]\+Error_Handler[[:space:]]*([[:space:]]*void[[:space:]]*)" "$dest_main_h"; then
224+
printf "void Error_Handler(void);\n" >> "$dest_main_h"
225+
fi
226+
fi
227+
else
228+
echo "WARNING: FSBL main.c not found at $fsbl_main_c; skipping clock_config generation" >&2
229+
fi
230+
231+
# Patch linker script to increase stack to 128 KiB (0x20000) for test workloads
232+
# Locate STM32N657XX_LRUN.ld under gcc/ or gcc/linker/
233+
ldpath=""
234+
for cand in \
235+
"$outp/gcc/linker/STM32N657XX_LRUN.ld" \
236+
"$outp/gcc/STM32N657XX_LRUN.ld" \
237+
$(find "$outp" -type f -name STM32N657XX_LRUN.ld 2>/dev/null | head -n1)
238+
do
239+
if [ -f "$cand" ]; then ldpath="$cand"; break; fi
240+
done
241+
if [ -n "$ldpath" ]; then
242+
echo "Patching stack size in $ldpath to 0x20000"
243+
# Common ST patterns
244+
sed -i.bak -E 's/(\b_Min_Stack_Size\s*=\s*)0x[0-9a-fA-F]+;/\10x20000;/' "$ldpath" || true
245+
sed -i.bak -E 's/(\b__STACK_SIZE\s*=\s*)0x[0-9a-fA-F]+;/\10x20000;/' "$ldpath" || true
246+
sed -i.bak -E 's/(\b__stack_size__\s*=\s*)0x[0-9a-fA-F]+;/\10x20000;/' "$ldpath" || true
247+
# If none of the vars exist, try to adjust the stack reservation directly
248+
if ! grep -Eq '\b_Min_Stack_Size\b|\b__STACK_SIZE\b|\b__stack_size__\b' "$ldpath"; then
249+
sed -i.bak -E 's/(\. = \. \+ )_Min_Stack_Size;/\10x20000;/' "$ldpath" || true
250+
fi
251+
else
252+
echo "WARNING: Could not find STM32N657XX_LRUN.ld to patch stack size" >&2
253+
fi
254+
'';
255+
256+
setupHook = writeText "setup-hook.sh" ''
257+
export NUCLEO_N657X0_Q_PATH="$1/platform/nucleo-n657x0-q/src/platform/"
258+
# Platform sources only; runtime debug server provided by STM32CubeCLT on host.
259+
'';
260+
261+
meta = {
262+
description = "Platform files for STM32 NUCLEO-N657X0-Q (use STM32Cube Command Line Tools gdbserver)";
263+
homepage = "https://github.com/STMicroelectronics/STM32CubeN6";
264+
};
265+
}

nix/util.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ rec {
106106
s2n_bignum = pkgs.callPackage ./s2n_bignum { };
107107
slothy = pkgs.callPackage ./slothy { };
108108
m55-an547 = pkgs.callPackage ./m55-an547-arm-none-eabi { };
109+
nucleo-n657x0-q = pkgs.callPackage ./nucleo-n657x0-q { };
109110
avr-toolchain = pkgs.callPackage ./avr { };
110111

111112
# Helper function to build individual cross toolchains

0 commit comments

Comments
 (0)