NixOS on ARM/Raspberry Pi 4: Difference between revisions
imported>Tobias.bora No edit summary |
Added instructions for getting bluetooth atleast usable |
||
(21 intermediate revisions by 13 users not shown) | |||
Line 4: | Line 4: | ||
!colspan="2" class="title"|Raspberry Pi 4 Family | !colspan="2" class="title"|Raspberry Pi 4 Family | ||
|- | |- | ||
|colspan="2"| | |colspan="2"|[[File:Raspberry_Pi_4,_2_GB_RAM_version_4.jpg|frameless|256px|A Raspberry Pi 4.]] | ||
|- | |- | ||
!Manufacturer | !Manufacturer | ||
Line 27: | Line 27: | ||
|} | |} | ||
</div> | </div> | ||
The Raspberry Pi family of devices is a series of single-board computers made by the Raspberry Pi Foundation. They are all based on Broadcom System-on-a-chip (SoCs). | The Raspberry Pi family of devices is a series of single-board computers made by the Raspberry Pi Foundation. They are all based on Broadcom System-on-a-chip (SoCs). | ||
== Status == | == Status == | ||
Line 37: | Line 37: | ||
First follow the [[NixOS_on_ARM#Installation|generic installation steps]] to get the installer image and install using the [[NixOS_on_ARM#NixOS_installation_.26_configuration|installation and configuration steps]]. | First follow the [[NixOS_on_ARM#Installation|generic installation steps]] to get the installer image and install using the [[NixOS_on_ARM#NixOS_installation_.26_configuration|installation and configuration steps]]. | ||
The Raspberry Pi 4B works with | The Raspberry Pi 4B works with the [https://hydra.nixos.org/job/nixos/trunk-combined/nixos.sd_image.aarch64-linux generic SD image]. | ||
Sample instructions for [https://nix.dev/tutorials/installing-nixos-on-a-raspberry-pi installing NixOS on a Raspberry Pi] are available at nix.dev. | Sample instructions for [https://nix.dev/tutorials/installing-nixos-on-a-raspberry-pi installing NixOS on a Raspberry Pi] are available at nix.dev. | ||
Line 45: | Line 45: | ||
=== Configuration === | === Configuration === | ||
Using <code>nixos-generate-config</code> will generate the required minimal configuration. | |||
For better GPU support and some deviceTree quirks add the nixos-hardware channel: | |||
<code> | |||
<code> | nix-channel --add https://github.com/NixOS/nixos-hardware/archive/master.tar.gz nixos-hardware | ||
nix-channel --update | |||
</code> | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
{ config, pkgs, lib, ... }: | { config, pkgs, lib, ... }: | ||
{ | { | ||
imports = | |||
[ | |||
</nowiki><<nowiki>nixos-hardware/raspberry-pi/4</nowiki>><nowiki> | |||
./hardware-configuration.nix | |||
]; | ]; | ||
hardware = { | |||
raspberry-pi."4".apply-overlays-dtmerge.enable = true; | |||
deviceTree = { | |||
enable = true; | enable = true; | ||
filter = "*rpi-4-*.dtb"; | |||
}; | }; | ||
}; | }; | ||
console.enable = false; | |||
environment.systemPackages = with pkgs; [ | |||
libraspberrypi | |||
raspberrypi-eeprom | |||
]; | |||
system.stateVersion = "23.11"; | |||
system.stateVersion = " | |||
} | } | ||
</nowiki>}} | </nowiki>}} | ||
Line 114: | Line 87: | ||
</nowiki>}} | </nowiki>}} | ||
Now reboot the device so it can update the firmware from boot partition. | Now reboot the device so it can update the firmware from the boot partition. | ||
=== GPU support === | === GPU support === | ||
Line 135: | Line 99: | ||
enable = true; | enable = true; | ||
displayManager.lightdm.enable = true; | displayManager.lightdm.enable = true; | ||
desktopManager. | desktopManager.gnome.enable = true; | ||
videoDrivers = [ "fbdev" ]; | videoDrivers = [ "fbdev" ]; | ||
}; | }; | ||
Line 142: | Line 106: | ||
==== With GPU ==== | ==== With GPU ==== | ||
In [https://github.com/NixOS/nixos-hardware/pull/261 nixos-hardware#261] | In [https://github.com/NixOS/nixos-hardware/pull/261 nixos-hardware#261] an option has been added to use the <code>fkms-3d</code> ([https://wiki.archlinux.org/title/Kernel_mode_setting modesetting]) overlay which uses the [https://www.raspberrypi.com/news/vc4-and-v3d-opengl-drivers-for-raspberry-pi-an-update/ V3D renderer]. This will only work with the vendor kernel, which is the default in NixOS. | ||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
Line 157: | Line 121: | ||
enable = true; | enable = true; | ||
displayManager.lightdm.enable = true; | displayManager.lightdm.enable = true; | ||
desktopManager. | desktopManager.gnome.enable = true; | ||
}; | }; | ||
} | } | ||
</nowiki>}} | </nowiki>}} | ||
=== Tools === | |||
The raspberry tools are available in the <code>libraspberrypi</code> package and include commands like <code>vcgencmd</code> to measure temperature and CPU frequency. | The raspberry tools are available in the <code>libraspberrypi</code> package and include commands like <code>vcgencmd</code> to measure temperature and CPU frequency. | ||
=== Audio === | |||
In addition to the usual config, you will need to enable hardware audio support: | |||
{{ | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
sound.enable = true; | |||
hardware.pulseaudio.enable = true; | |||
hardware.raspberry-pi."4".audio.enable = true; | |||
</nowiki>}} | |||
For audio through hdmi: | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
sound.enable = true; | sound.enable = true; | ||
hardware.pulseaudio.enable = true; | hardware.pulseaudio.enable = true; | ||
boot.kernelParams = [ | |||
"snd_bcm2835.enable_hdmi=1"]; | |||
</nowiki>}} | |||
=== Using GPIO pins as non-root === | |||
By default, the GPIO pins are enabled, but can only be accessed by the root user. | |||
This can be addressed by adding a [https://wiki.archlinux.org/title/Udev udev] rule to your configuration that changes the ownership of <code>/dev/gpiomem</code> and the other required devices. | |||
</ | |||
The following code adds a group <code>gpio</code> and adds the user <code>mygpiouser</code> to that group. You probably want to put your own user name here. | |||
The <code>extraRules</code> changes the owner of <code>gpiomem</code> and all other files needed for GPIO to work to <code>root:gpio</code> and changes the permissions to <code>0660</code>. | |||
Therefore, the root user and anyone in the gpio group can now access the GPIO pins. | |||
<syntaxHighlight lang="nix"> | |||
# | # Create gpio group | ||
users.groups.gpio = {}; | users.groups.gpio = {}; | ||
# | # Change permissions gpio devices | ||
services.udev.extraRules = '' | services.udev.extraRules = '' | ||
SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio",MODE="0660" | SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio",MODE="0660" | ||
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", RUN+="${pkgs.bash}/bin/bash -c 'chown root:gpio | SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", RUN+="${pkgs.bash}/bin/bash -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'" | ||
SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add",RUN+="${pkgs.bash}/bin/bash -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'" | SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add",RUN+="${pkgs.bash}/bin/bash -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'" | ||
''; | ''; | ||
# | # Add user to group | ||
users = { | users = { | ||
users.mygpiouser = { | users.mygpiouser = { | ||
extraGroups = [ "gpio" ... ]; | |||
.... | |||
extraGroups = [ | |||
}; | }; | ||
}; | }; | ||
</syntaxHighlight> | |||
=== Enabling the SPI === | |||
To enable the SPI, you would normally add <code>dtparam=spi=on</code> to <code>/boot/config.txt</code>. | |||
This is not possible on NixOS, and instead you have to apply a device tree overlay. | |||
For this we use the <code>hardware.deviceTree.overlays</code> option. | |||
After applying the overlay, we add an <code>spi</code> group and change the owner of the <code>spidev</code> device to it, similarly to [[#Using GPIO pins as non root |GPIO]]. | |||
<syntaxHighlight lang="nix"> | |||
hardware.raspberry-pi."4".apply-overlays-dtmerge.enable = true; | |||
hardware.deviceTree = { | |||
enable = true; | |||
filter = "*-rpi-*.dtb"; | |||
overlays = [ | |||
{ | |||
name = "spi"; | |||
dtsoFile = ./spi0-0cd.dtso; | |||
} | |||
]; | |||
}; | |||
users.groups.spi = {}; | |||
services.udev.extraRules = '' | |||
SUBSYSTEM=="spidev", KERNEL=="spidev0.0", GROUP="spi", MODE="0660" | |||
''; | |||
</syntaxHighlight> | |||
</ | The the <code>spi0-0cd.dtso</code> file can be downloaded [https://github.com/raspberrypi/firmware/blob/master/boot/overlays/spi0-0cs.dtbo here]. | ||
You might have to change the <code>compatible</code> field to "raspberrypi" in the dtbo file. | |||
=== HDMI-CEC === | === HDMI-CEC === | ||
Line 218: | Line 219: | ||
# an overlay to enable raspberrypi support in libcec, and thus cec-client | # an overlay to enable raspberrypi support in libcec, and thus cec-client | ||
nixpkgs.overlays = [ | nixpkgs.overlays = [ | ||
(self: super: { libcec = super.libcec.override { inherit (self) libraspberrypi; }; }) | # nixos-22.05 | ||
# (self: super: { libcec = super.libcec.override { inherit (self) libraspberrypi; }; }) | |||
# nixos-22.11 | |||
(self: super: { libcec = super.libcec.override { withLibraspberrypi = true; }; }) | |||
]; | ]; | ||
Line 230: | Line 234: | ||
services.udev.extraRules = '' | services.udev.extraRules = '' | ||
# allow access to raspi cec device for video group (and optionally register it as a systemd device, used below) | # allow access to raspi cec device for video group (and optionally register it as a systemd device, used below) | ||
KERNEL=="vchiq", GROUP="video", MODE="0660", TAG+="systemd", ENV{SYSTEMD_ALIAS}="/dev/vchiq" | |||
''; | ''; | ||
# optional: attach a persisted cec-client to `/run/cec.fifo`, to avoid the CEC ~1s startup delay per command | # optional: attach a persisted cec-client to `/run/cec.fifo`, to avoid the CEC ~1s startup delay per command | ||
# scan for devices: `echo 'scan' > /run/cec.fifo ; journalctl -u cec-client.service` | # scan for devices: `echo 'scan' </nowiki>><nowiki> /run/cec.fifo ; journalctl -u cec-client.service` | ||
# set pi as active source: `echo 'as' > /run/cec.fifo` | # set pi as active source: `echo 'as' </nowiki>><nowiki> /run/cec.fifo` | ||
systemd.sockets."cec-client" = { | systemd.sockets."cec-client" = { | ||
after = [ "dev-vchiq.device" ]; | after = [ "dev-vchiq.device" ]; | ||
Line 252: | Line 256: | ||
serviceConfig = { | serviceConfig = { | ||
ExecStart = ''${pkgs.libcec}/bin/cec-client -d 1''; | ExecStart = ''${pkgs.libcec}/bin/cec-client -d 1''; | ||
ExecStop = ''/bin/sh -c "echo q > /run/cec.fifo"''; | ExecStop = ''/bin/sh -c "echo q </nowiki>><nowiki> /run/cec.fifo"''; | ||
StandardInput = "socket"; | StandardInput = "socket"; | ||
StandardOutput = "journal"; | StandardOutput = "journal"; | ||
Line 258: | Line 262: | ||
}; | }; | ||
} | } | ||
</nowiki>}} | |||
=== Enabling Bluetooth === | |||
One might get bluetooth to work with this in the configuration file: | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
systemd.services.btattach = { | |||
before = [ "bluetooth.service" ]; | |||
after = [ "dev-ttyAMA0.device" ]; | |||
wantedBy = [ "multi-user.target" ]; | |||
serviceConfig = { | |||
ExecStart = "${pkgs.bluez}/bin/btattach -B /dev/ttyAMA0 -P bcm -S 3000000"; | |||
}; | |||
}; | |||
</nowiki>}} | </nowiki>}} | ||
Line 274: | Line 292: | ||
== Troubleshooting == | == Troubleshooting == | ||
=== | === Audio not playing and Bluetooth: no controller available === | ||
On the Raspberry Pi kernel, the jack may never play audio, and no Bluetooth devices may ever be found. To get this to work, it is recommended to switch to the mainline kernel. See [https://github.com/NixOS/nixpkgs/issues/123725 nixpkgs#123725] for more info. | |||
< | === Touch screen not working === | ||
You have to declare this in your <code>configuration.nix</code><ref>https://discourse.nixos.org/t/cant-get-nixos-x-to-work-on-a-raspberry-pi-with-dsi-display/44532/3</ref>:<syntaxhighlight lang="nix"> | |||
hardware.raspberry-pi."4" = { | |||
touch-ft5406.enable = true; | |||
}; | |||
</syntaxhighlight> |