Difference between revisions of "NixOS on ARM/Raspberry Pi 4"

From NixOS Wiki
Jump to: navigation, search
m (fix more angle brackets in code sample)
m (rollback unauthorized mass edits)
Tag: Rollback
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{ARM/breadcrumb}}
+
This page has been moved to the official NixOS Wiki:
<div class="infobox">
 
{|class="table"
 
!colspan="2" class="title"|Raspberry Pi 4 Family
 
|-
 
|colspan="2"|[[File:Raspberry_Pi_4,_2_GB_RAM_version_4.jpg|frameless|256px|A Raspberry Pi 4.]]
 
|-
 
!Manufacturer
 
|Raspberry Pi Foundation
 
|-
 
!Architecture
 
|AArch64
 
|-
 
!Bootloader
 
|Custom or U-Boot
 
|-
 
!Boot order
 
|Configurable; SD, USB, Netboot
 
|-
 
!Maintainer
 
|
 
|-
 
!colspan="2" class="title"|Raspberry Pi 4B
 
|-
 
!SoC
 
|BCM2711
 
|}
 
</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).
 
  
== Status ==
+
    ⇒ '''[https://wiki.nixos.org/wiki/NixOS_on_ARM/Raspberry_Pi_4 NixOS on ARM/Raspberry Pi 4]'''
  
The Raspberry Pi 4 Family is only supported as '''AArch64'''. Use as armv7 is community supported.
+
''— samueldr, Lead of NixOS on ARM.''
 
 
== Board-specific installation notes ==
 
 
 
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 [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.
 
 
 
{{warning| Note that the Raspberry Pi 4 has two HDMI outputs, and apparently sometimes the user prompt for the console/TTY is displayed on HDMI 1 while the boot process is displayed on HDMI 0 (this may even [https://raspberrypi.stackexchange.com/a/112071/149250 be the case] with the official (non NixOs) non-graphical lite image). So if after the message "Welcome on NixOs" at the end of phase 2 your screen goes black/disconnects, try to use the other HDMI port. See the related bug [https://github.com/NixOS/nixpkgs/issues/179701 here].}}
 
 
 
=== 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>
 
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>
 
{ 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;
 
      filter = "*rpi-4-*.dtb";
 
    };
 
  };
 
  console.enable = false;
 
  environment.systemPackages = with pkgs; [
 
    libraspberrypi
 
    raspberrypi-eeprom
 
  ];
 
  system.stateVersion = "23.11";
 
}
 
</nowiki>}}
 
=== USB boot ===
 
 
 
For USB booting to work properly, a firmware update might be needed:
 
 
 
{{commands|<nowiki>
 
$ nix-shell -p raspberrypi-eeprom
 
$ rpi-eeprom-update -d -a
 
</nowiki>}}
 
 
 
Now reboot the device so it can update the firmware from the boot partition.
 
 
 
=== GPU support ===
 
 
 
The following configuration samples are built on the assumption that they are added to an already working configuration. They are not complete configurations.
 
 
 
==== Without GPU ====
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
 
{
 
  services.xserver = {
 
    enable = true;
 
    displayManager.lightdm.enable = true;
 
    desktopManager.gnome.enable = true;
 
    videoDrivers = [ "fbdev" ];
 
  };
 
}
 
</nowiki>}}
 
==== With GPU ====
 
 
 
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>
 
{ pkgs, ... }:
 
 
 
{
 
  imports = [
 
    .../nixos-hardware/raspberry-pi/4
 
  ];
 
 
 
  hardware.raspberry-pi."4".fkms-3d.enable = true;
 
 
 
  services.xserver = {
 
    enable = true;
 
    displayManager.lightdm.enable = true;
 
    desktopManager.gnome.enable = true;
 
  };
 
}
 
</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.
 
 
 
=== 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>}}
 
 
 
=== 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 = {};
 
 
 
  # Change permissions gpio devices
 
  services.udev.extraRules = ''
 
    SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio",MODE="0660"
 
    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'"
 
  '';
 
 
 
  # Add user to group
 
  users = {
 
    users.mygpiouser = {
 
      extraGroups = [ "gpio" ... ];
 
      ....
 
    };
 
  };
 
</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 possbible 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 ===
 
 
 
A few bits and pieces for using HDMI-CEC on the Pi4:
 
 
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
 
{ pkgs, ... }:
 
 
 
{
 
  # an overlay to enable raspberrypi support in libcec, and thus cec-client
 
  nixpkgs.overlays = [
 
    # nixos-22.05
 
    # (self: super: { libcec = super.libcec.override { inherit (self) libraspberrypi; }; })
 
    # nixos-22.11
 
    (self: super: { libcec = super.libcec.override { withLibraspberrypi = true; }; })
 
  ];
 
 
 
  # install libcec, which includes cec-client (requires root or "video" group, see udev rule below)
 
  # scan for devices: `echo 'scan' | cec-client -s -d 1`
 
  # set pi as active source: `echo 'as' | cec-client -s -d 1`
 
  environment.systemPackages = with pkgs; [
 
    libcec
 
  ];
 
 
 
  services.udev.extraRules = ''
 
    # 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
 
  # scan for devices: `echo 'scan' </nowiki>><nowiki> /run/cec.fifo ; journalctl -u cec-client.service`
 
  # set pi as active source: `echo 'as' </nowiki>><nowiki> /run/cec.fifo`
 
  systemd.sockets."cec-client" = {
 
    after = [ "dev-vchiq.device" ];
 
    bindsTo = [ "dev-vchiq.device" ];
 
    wantedBy = [ "sockets.target" ];
 
    socketConfig = {
 
      ListenFIFO = "/run/cec.fifo";
 
      SocketGroup = "video";
 
      SocketMode = "0660";
 
    };
 
  };
 
  systemd.services."cec-client" = {
 
    after = [ "dev-vchiq.device" ];
 
    bindsTo = [ "dev-vchiq.device" ];
 
    wantedBy = [ "multi-user.target" ];
 
    serviceConfig = {
 
      ExecStart = ''${pkgs.libcec}/bin/cec-client -d 1'';
 
      ExecStop = ''/bin/sh -c "echo q </nowiki>><nowiki> /run/cec.fifo"'';
 
      StandardInput = "socket";
 
      StandardOutput = "journal";
 
      Restart="no";
 
  };
 
}
 
</nowiki>}}
 
 
 
== Notes about the boot process ==
 
 
 
Unless using an extremely early WIP image, the Raspberry Pi 4B boots using the U-Boot platform firmware.
 
 
 
=== Updating U-Boot/Firmware ===
 
 
 
{{commands| <nowiki>
 
$ nix-shell -p raspberrypi-eeprom
 
$ sudo mount /dev/disk/by-label/FIRMWARE /mnt
 
$ sudo BOOTFS=/mnt FIRMWARE_RELEASE_STATUS=stable rpi-eeprom-update -d -a
 
</nowiki>}} [https://nix.dev/tutorials/installing-nixos-on-a-raspberry-pi#updating-firmware source]
 
 
 
== 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.
 

Latest revision as of 11:02, 6 April 2024

This page has been moved to the official NixOS Wiki:

    ⇒ NixOS on ARM/Raspberry Pi 4

— samueldr, Lead of NixOS on ARM.