klipper-flash: rewrite flasher script

This completely removes gcc/make from the update loop, and fixes it for
at least some boards.

Although only tested on some boards, and probably lacking support
for some, that's vastly better than sending avr-gcc to your RPi every
update, and not working afterwards.

This also introduces makeFlasher in firmware passthroughs. Use it like
so:
```
  firmware = klipper-firmware.override {
    mcu = "myprinter";
    firmwareConfig = ./config;
  };
  flasher = firmware.makeFlasher {
    flashDevice = "/dev/ttyACM0";
  };
```
This commit is contained in:
Cabia Rangris 2025-07-14 02:11:47 +04:00 committed by Cabia Rangris
parent 9d1eed5445
commit f8de8add74
2 changed files with 87 additions and 32 deletions

View File

@ -1,4 +1,5 @@
{
args@{
klipper-firmware,
stdenv,
lib,
pkg-config,
@ -12,9 +13,19 @@
klipper,
avrdude,
stm32flash,
klipper-flash,
mcu ? "mcu",
firmwareConfig ? ./simulator.cfg,
}:
# are used by flash scripts
# find those with `rg '\[\"lib'` inside of klipper repo
let
flashBinaries = [
"lib/bossac/bin/bossac"
"lib/hidflash/hid-flash"
"lib/rp2040_flash/rp2040_flash"
];
in
stdenv.mkDerivation rec {
name = "klipper-firmware-${mcu}-${version}";
version = klipper.version;
@ -38,7 +49,7 @@ stdenv.mkDerivation rec {
chmod +w ./.config
echo qy | { make menuconfig >/dev/null || true; }
if ! diff ${firmwareConfig} ./.config; then
echo " !!! Menuconfig has changed. Please update your configuration."
echo " !!! Klipper KConfig has changed. Please run klipper-genconf to update your configuration."
fi
'';
@ -46,6 +57,11 @@ stdenv.mkDerivation rec {
patchShebangs .
'';
postBuild = ''
# build flash binaries
${with builtins; concatStringsSep "\n" (map (path: "make ${path} $out/bin/ || true") flashBinaries)}
'';
makeFlags = [
"V=1"
"WXVERSION=3.2"
@ -57,14 +73,47 @@ stdenv.mkDerivation rec {
cp out/klipper.bin $out/ || true
cp out/klipper.elf $out/ || true
cp out/klipper.uf2 $out/ || true
mkdir -p $out/lib/
${
with builtins;
concatStringsSep "\n" (
map (path: ''
if [ -e ${path} ]; then
mkdir -p $out/$(dirname ${path})
cp -r ${path} $out/$(dirname ${path})
fi
'') flashBinaries
)
}
rmdir $out/lib 2>/dev/null || echo "Flash binaries exist, not cleaning up lib/"
'';
dontFixup = true;
passthru = {
makeFlasher =
{ flashDevice }:
klipper-flash.override {
klipper-firmware = klipper-firmware.override args;
inherit
klipper
firmwareConfig
mcu
flashDevice
;
};
};
meta = with lib; {
inherit (klipper.meta) homepage license;
description = "Firmware part of Klipper";
maintainers = with maintainers; [ vtuan10 cab404 ];
maintainers = with maintainers; [
vtuan10
cab404
];
platforms = platforms.linux;
};
}

View File

@ -1,47 +1,53 @@
{
lib,
writeShellApplication,
gnumake,
pkgsCross,
klipper,
klipper-firmware,
python3,
avrdude,
dfu-util,
stm32flash,
mcu ? "mcu",
flashDevice ? "/dev/null",
firmwareConfig ? ./simulator.cfg,
}:
let
supportedArches = [
"avr"
"stm32"
"lpc176x"
];
matchBoard =
getConfigField =
field:
with builtins;
match ''^.*CONFIG_BOARD_DIRECTORY="([a-zA-Z0-9_]+)".*$'' (readFile firmwareConfig);
boardArch = if matchBoard == null then null else builtins.head matchBoard;
let
matches = match ''^.*${field}="([a-zA-Z0-9_]+)".*$'' (readFile firmwareConfig);
in
if matches != null then head matches else null;
matchPlatform = getConfigField "CONFIG_BOARD_DIRECTORY";
matchBoard = getConfigField "CONFIG_MCU";
in
writeShellApplication {
name = "klipper-flash-${mcu}";
runtimeInputs = [
python3
pkgsCross.avr.stdenv.cc
gnumake
]
++ lib.optionals (boardArch == "avr") [ avrdude ]
++ lib.optionals (boardArch == "stm32") [ stm32flash ];
text = ''
if ${lib.boolToString (!builtins.elem boardArch supportedArches)}; then
printf "Flashing Klipper firmware to your board is not supported yet.\n"
printf "Please use the compiled firmware at ${klipper-firmware} and flash it using the tools provided for your microcontroller."
exit 1
fi
if ${lib.boolToString (boardArch == "stm32")}; then
make -C ${klipper.src} FLASH_DEVICE="${toString flashDevice}" OUT="${klipper-firmware}/" KCONFIG_CONFIG="${klipper-firmware}/config" serialflash
runtimeInputs =
[ ]
++ lib.optionals (matchPlatform == "avr") [ avrdude ]
++ lib.optionals (matchPlatform == "stm32") [
stm32flash
dfu-util
]
++ lib.optionals (matchPlatform == "lpc176x") [ dfu-util ]
# bossac, hid-flash and RP2040 flash binaries are built by klipper-firmware
;
text =
# generic USB script for most things with serial and bootloader (see MCU_TYPES in scripts/flash_usb.py)
if matchBoard != null && matchPlatform != null then
''
pushd ${klipper-firmware}
${klipper}/lib/scripts/flash_usb.py -t ${matchBoard} -d ${flashDevice} ${klipper-firmware}/klipper.bin $@
popd
''
else
make -C ${klipper.src} FLASH_DEVICE="${toString flashDevice}" OUT="${klipper-firmware}/" KCONFIG_CONFIG="${klipper-firmware}/config" flash
fi
'';
''
cat <<EOF
Board pair ${toString matchBoard}/${toString matchPlatform} (config ${firmwareConfig}) is not supported in NixOS auto flashing script.
Please manually flash the firmware using the appropriate tool for your board.
Built firmware is located here:
${klipper-firmware}
EOF
'';
}