lilyinstarlight / zmk-nix

Build system and configuration files for generating and building ZMK firmware with Nix
MIT License
56 stars 14 forks source link

Add alternative flash method for Nice!Nano's #80

Open nakato opened 2 months ago

nakato commented 2 months ago

The Nice!Nano's with the adafruit bootloader, the default one, have three ways they can be flashed that I know of.

  1. Mount as filesystem and copy the file over
  2. writing uf2 file directly into device, such as with dd
  3. Using adafruit-nrfdfu

1 is what is currently used, it requires a mounting tool in user-space or root privileges to mount the device, and the user needs to know to mount it with options to give user permissions to access the filesystem, eg mount -o rw,uid=$(id -u user),gid=$(id -g user) /dev/sdX /mnt/nn.

The most annoying part of this method however is that the device just disappears when the file copy is done. Sometimes it leaves the device in the kernel uncleanly, so the next disk that appears, such as the second n!n will be at /dev/sdY. If the user is copying the files manually and attempts to chain the umount command, this can regularly cause umount to stick in uninterruptible sleep, which is painful to correct as it requires rebooting and the reboot cannot be performed cleanly.

The dd method is pretty good, but it requires root privileges again, or possibly some custom udev rules to change the permissions on block device so a regular user can perform the action, but DDing the start of a disk is a bit scary and likely to raise eyebrows, so that method is probably best not used here.

Finally, the 3rd method. The bootloader exposes a serial port, this can be used via the adafruit-nrfdfu utility to write the application to the device as well, and that's what is being added here. The only requirement is the user is part of the dialout group so they have access to serial ports. The user puts the device into bootloader mode, and the flash proceeds without additional input.

To use this, I update flash to:

flash = zmk-nix.packages.''${system}.flash-nicenano-dfu.override { inherit firmware; };

and run

NIXPKGS_ALLOW_UNFREE=1 nix run --impure -L .#flash
nakato commented 2 months ago

The CI failure has been caused by the license of adafruit-nrfutil being unfree, and that has caused nix flake check to fail.

Short of changing all the CI scripts to include NIXPKGS_ALLOW_UNFREE=1 and running them with --impure I'm unsure of how to resolve this, do you have any ideas?

I tried to use other implementations of nrfdfu, however they won`t work with the adafruit bootloader, so switching to a different implementation isn't a possible solution sadly.

lilyinstarlight commented 2 months ago

Yeahh I noticed that. I'll figure something out for that when I get a chance to review this, hopefully within the next few days :)

Thank you so much for working on this! <3

nakato commented 2 months ago

I'm working on an alternative method I'll push up in a separate PR along this one for consideration. It uses the block-device method, but I think I'll be able to address all my apprehensions to that method to the point it will not be scary to anyone. The downside to it is that it will require a udev rule to work, but it'll side-step the unfree issue for now.

Thank you for this! It's amazing to be able to build locally without a massive Zephyr fight!