QMK keyboard flashing on nix

Posted on February 19, 2022

Well, I finally ‘finished’ the 40% keyboard - screwed the screws onto the case, wrote and flashed the firmware and all that. I don’t think the hardware assembly is particularly interesting or difficult (just remember to measure carefully and remember that it doesnt really matter what sizing you pick as long as it fits together on the inside). The keyboard isnt too bad, although I think I might swap Fn1 and Fn2 as I think having the primary farther out is more ergonomic, although of course it depends on what finger you like to use to press it I suppose. Anyway, on nix the flashing process was a little tricky to start out. I assumed having gcc installed would be enough, but I needed avr-gcc and a whole host of other things. So firstly, clone the git repository for qmk, which I typically use. I think there is a way to compile it from source and then use the <repo>/bin/qmk as the binary, but I couldn’t be bothered to do it/figure out how. I instead just installed qmk as well (I’ll have to remember to remove it from my configuration.nix later) and that worked fine enough. Next step is to go to the keyboards directory and find your keyboard version (I think if this is a totally custom/handwired keyboard you should know how to do this instead of reading this) and take a look at the keymaps that other people have hopefully made before you. I personally like copying a keymap over to my personal folder and modifying it from there. The qmk website and git both have good documentation with regards to keycodes, which is super helpful, even though I am personally not into a lot of the more complex options (like tapping and holding being two different things). After the keymap is written, its now time to compile with qmk compile -kb <keyboard-name> -km <keymap-name>. Keymap name is the name of the folder in the keymaps folder. The compile command will give you pretty standard C errors if you get something wrong, which is helpful as the issues are pretty clear here. On nixOS however, the avr-gcc issue showed up here, as my system is x86_64, and so I need to do something called cross-compile. To cross compile, I wrote a file avrShell.nix as follows

with import <nixpkgs> {
  crossSystem = {
    config = "avr";
  };
};

mkShell {
  buildInputs = [ ]; # your dependencies here
}

Typically the config is some generic architecture but if you put avr in, it will enter a temporary nix shell with avr compilation facility. I also needed the usbutils package for lsusb to see the keyboard as well as the dfu-programmer package, but I dont know where to stick them in that nix shell file. Instead, after running nix-shell avrShell.nix, also run nix-shell -p usbutils and nix-shell -p dfu-programmer

we can then compile with the earlier qmk compile command, which will deposit a .hex file into .build folder. then its pretty simple to flash the new configuration keymap onto the keyboard. Reset the keyboard (hopefully you haven’t already installed the keyboard like I did, or there is a key combo to reset like I luckily did; I would recommend placing a keycombo reset out of the way though, it’ll be very helpful when iterating), and then you can run the following commands:

sudo dfu-programmer atmega32u4 erase
sudo dfu-programmer atmega32u4 flash ./.build/<keyboardname>.hex
sudo dfu-programmer atmega32u4 reset

I think it is for some reason, pretty important to use sudo here, but you can for sure try and see if it works without if you wish. Of course if you have a different microcontroller than an atmega32u4 then it will be a different name. The command lsusb should tell you what the name of the microcontroller is, once the keyboard has been reset. I inserted those three commands into a bash file, so I could just run the bash file to erase and flash the compiled hex onto the keyboard quickly. I think you could probably also include the compile step in there, and have very quick/easy iterations on keymaps.

Honestly, I think nixOS makes flashing the keyboard a little more tricky, but it isn’t too bad. I definitely think that if I knew more about nix shells, it could be really easy after the first time; just automatically enter the shell and then run a bash script to compile, erase, flash and reset the keyboard.