|
| 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 | +} |
0 commit comments