From f8de8add748d049e9a8bdc0c549db74412ca28c2 Mon Sep 17 00:00:00 2001 From: Cabia Rangris Date: Mon, 14 Jul 2025 02:11:47 +0400 Subject: [PATCH] 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"; }; ``` --- pkgs/servers/klipper/klipper-firmware.nix | 55 +++++++++++++++++-- pkgs/servers/klipper/klipper-flash.nix | 64 +++++++++++++---------- 2 files changed, 87 insertions(+), 32 deletions(-) diff --git a/pkgs/servers/klipper/klipper-firmware.nix b/pkgs/servers/klipper/klipper-firmware.nix index 63feb8b07455..5be57bbf5d92 100644 --- a/pkgs/servers/klipper/klipper-firmware.nix +++ b/pkgs/servers/klipper/klipper-firmware.nix @@ -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; }; } diff --git a/pkgs/servers/klipper/klipper-flash.nix b/pkgs/servers/klipper/klipper-flash.nix index 7a6652580654..95f8a261ebcd 100644 --- a/pkgs/servers/klipper/klipper-flash.nix +++ b/pkgs/servers/klipper/klipper-flash.nix @@ -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 <