NixOS on ARM/Raspberry Pi: Difference between revisions

From NixOS Wiki
imported>Rogarb
No edit summary
m →‎Power issues: Made the text less vague and removed a redundant word.
 
(10 intermediate revisions by 7 users not shown)
Line 31: Line 31:
== Status ==
== Status ==


Only the ''Raspberry Pi 3 Family'' is supported upstream, with the AArch64 effort.
Only the ''Raspberry Pi 3 Family'' is supported upstream, with the AArch64 effort. Other Raspberry Pis are part of '''@dezgeg''''s porting efforts to ARMv6 and ARMv7.
 
The Raspberry Pi 4B may require using the vendor kernel for better hardware support.
 
Other Raspberry Pis (0, 1, and 2) are part of diverse community porting efforts to ARMv6 and ARMv7.


The Linux kernel in use, except for the Raspberry Pi 1 family, is the mainline Linux kernel, and not the Raspberry Pi Foundation's fork. This could reduce compatibility with some add-on boards or third-party libraries<sup>[expanded explanation needed]</sup>.
The Linux kernel in use, except for the Raspberry Pi 1 family, is the mainline Linux kernel, and not the Raspberry Pi Foundation's fork. This could reduce compatibility with some add-on boards or third-party libraries<sup>[expanded explanation needed]</sup>.
Line 46: Line 42:
! Architecture
! Architecture
! Support
! Support
|-
!colspan="3" style="text-align: left;"|Raspberry Pi Zero
|-
| Raspberry Pi Zero
|rowspan="2" stype="vertical-align: middle;"|armv6
| C*
|-
| Raspberry Pi Zero W
| C
|-
| Raspberry Pi Zero 2 W
|armv7
| ?
|-
|-
!colspan="3" style="text-align: left;"|Raspberry Pi 1
!colspan="3" style="text-align: left;"|Raspberry Pi 1
|-
|-
| Raspberry Pi 1 Model B
| Raspberry Pi 1 Model B
|rowspan="3" style="vertical-align: middle;"| armv6
|rowspan="5" style="vertical-align: middle;"| armv6
| C
| C
|-
|-
Line 70: Line 53:
|-
|-
| Raspberry Pi 1 Model B+
| Raspberry Pi 1 Model B+
| C
|-
| Raspberry Pi Zero
| C*
|-
| Raspberry Pi Zero W
| C
| C
|-
|-
Line 80: Line 69:
!colspan="3" style="text-align: left;"|Raspberry Pi 3
!colspan="3" style="text-align: left;"|Raspberry Pi 3
|-
|-
| [[NixOS on ARM/Raspberry Pi 3|Raspberry Pi 3 Model B]]
| Raspberry Pi 3 Model B
|rowspan="3" style="vertical-align: middle;"| AArch64<br /> ''+ armv7''
|rowspan="3" style="vertical-align: middle;"| AArch64<br /> ''+ armv7''
| YES
| YES
|-
|-
| [[NixOS on ARM/Raspberry Pi 3|Raspberry Pi 3 Model B+]]
| Raspberry Pi 3 Model B+
| YES
| YES
|-
|-
| [[NixOS on ARM/Raspberry Pi 3|Raspberry Pi 3 Model A+]]
| Raspberry Pi 3 Model A+
| ?
| ?
|-
|-
!colspan="3" style="text-align: left;"|Raspberry Pi 4
!colspan="3" style="text-align: left;"|Raspberry Pi 4
|-
|-
| [[NixOS on ARM/Raspberry Pi 4|Raspberry Pi 4 Model B]]
| Raspberry Pi 4 Model B
| AArch64<br /> ''+ armv7''
| AArch64<br /> ''+ armv7''
| YES
| YES
Line 100: Line 89:
| Raspberry Pi 400
| Raspberry Pi 400
| AArch64<br /> ''+ armv7''
| AArch64<br /> ''+ armv7''
| Yes (only with kernel >= 6.1)
| Yes (only with kernel >= 6.1)  
|}
|}


''Support''
''Support''
* YES: Supported architecture by Nixpkgs downstream and tested to be working.
* YES: Supported architecture by Nixpkgs downstream and tested to be working.
* YES*: Available in Nixpkgs downstream but experimental.
* C: Community supported, and tested to be working.
* C: Community supported, and tested to be working.
* C*: Community supported, unverified but should be working.
* C*: Community supported, unverified but should be working.
Line 117: Line 105:


=== Raspberry Pi (1) ===
=== Raspberry Pi (1) ===
The ARMv6 image boots out-of-the-box. The instructions to build an image for ARMv6 are adapted from [[NixOS_on_ARM#Build_your_own_image_natively|here]].


First, create your own configuration in sd-image.nix (adding cross-compiling information if needed):
The ARMv6 image boots out-of-the-box.
<syntaxHighlight lang=nix>
 
# save as sd-image.nix somewhere
=== Raspberry Pi 2 ===
{ ... }: {
 
  # uncomment for enabling cross compilation
The ARMv7 image should boot out-of-the-box, though the author hasn't personally tested this.
  #nixpkgs.crossSystem.system = "armv6l-linux";
 
  imports = [
=== Raspberry Pi 3 / 3B+ ===
    # This contains the default definition for the sdcard image build
 
    <nixpkgs/nixos/modules/installer/sd-card/sd-image-raspberrypi.nix>
Both the AArch64 and ARMv7 images boot out-of-the-box. Using the 64-bit AArch64 image is highly recommended, as the availability of binaries is much better and allows the use of the 64-bit instruction set.
  ];
 
  # put your own configuration here, for example ssh keys:
For the UART console, edit <code>/extlinux/extlinux.conf</code> on the boot partition of the SD card to set <code>console=ttyS1,115200n8</code> in the kernel boot parameters, and use the following GPIO Pins with an USB-TTL connector:  
   #users.users.root.openssh.authorizedKeys.keys = [
<syntaxhighlight>
   #  "ssh-ed25519 AAAAC3NzaC1lZDI1.... username@tld"
GND        - 3rd in top row, black cable
  #];
GPIO 14 TXD - 4th in top row, white cable
GPIO 15 RXD - 5th in top row, green cable
</syntaxhighlight>
Use <code>nix-shell -p screen --run "screen /dev/ttyUSB0 115200"</code> to connect to the console.  
{{note|The mainline kernel (tested with nixos kernel 4.18.7) [https://github.com/raspberrypi/linux/wiki/Upstreaming#downstream-drivers does not include support for cpu frequency scaling] on the Raspberry Pi. To get higher clock speed, set [https://www.raspberrypi.org/documentation/configuration/config-txt/overclocking.md <code><nowiki>force_turbo=1</nowiki></code>] in <code>/boot/config.txt</code> }}
 
<syntaxhighlight lang=nix>
{
   hardware.enableRedistributableFirmware = true;
   networking.wireless.enable = true;
}
}
</syntaxHighlight>
</syntaxhighlight>
 
==== HDMI output issue with kernel 5.4 (NixOS 20.03 or NixOS unstable) ====
 
(Unverified for 5.5 or 5.6)
 
Some users have reported that the 5.4 kernel "hung at Starting kernel..." {{issue|82455}}. In all cases where it was possible to investigate, it was found that the device did boot, but that the HDMI out didn't function as expected.
 
It looks like it may be a setup-dependent issue, as a 20.03 image with 5.4 was verified as working.
 
If your setup is having the issue, first report on {{issue|82455}} with the Raspberry Pi model (important to note whether it is a plus or non-plus) and the kind of display used with the HDMI out, including whether it is using adapters or not.
 
Then, you can work around the issue by configuring your system to use the 4.19 kernel (previous LTS) using one of the following tricks.


Then build the image:
# Use the serial console to configure the system, and <code>nixos-rebuild boot</code> it.
# Use a 19.09 image, specify the kernel in its configuration and upgrade to 20.03
# Boot the image, poweroff blindly using a keyboard, edit on another computer <code>/home/nixos/.ssh/authorized_keys</code> from the SD to add your key file, chmod as 600, unmount, boot the Raspberry Pi and find it on your network by some means.


<syntaxHighlight lang=nix>
<syntaxHighlight>
$ nix-build '<nixpkgs/nixos>' -A config.system.build.sdImage -I nixos-config=./sd-image.nix
{
  boot.kernelPackages = pkgs.linuxPackages_4_19;
}
</syntaxHighlight>
</syntaxHighlight>


=== Raspberry Pi 2 ===
=== Raspberry Pi 4 ===
''See'' [[NixOS on ARM/Raspberry Pi 4]]


The ARMv7 image should boot out-of-the-box, though the author hasn't personally tested this.
=== Raspberry Pi 5===
''See'' [[NixOS on ARM/Raspberry Pi 5]]


=== Raspberry Pi 3 / 3B+ ===
== Audio ==


[[NixOS_on_ARM/Raspberry_Pi_3#Board-specific_installation_notes|Raspberry Pi 3#Board-specific installation notes]]
In addition to the usual config, it might be required to enable audio support explicitly in the firmwareConfig.


=== Raspberry Pi 4B ===
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
  sound.enable = true;
  hardware.pulseaudio.enable = true;


[[NixOS_on_ARM/Raspberry_Pi_4#Board-specific_installation_notes|Raspberry Pi 4#Board-specific installation notes]]
  boot.loader.raspberryPi.firmwareConfig = ''
    dtparam=audio=on
  '';
</nowiki>}}


== Serial console==
== Serial console==
Line 166: Line 185:
}
}
</nowiki>}}
</nowiki>}}
If the Raspberry Pi downstream kernel is used the serial interface is named <code>serial0</code> instead.
If the Raspberry Pi downstream kernel is used the serial interface is named <code>serial0</code> instead.


== Bluetooth ==
The bluetooth controller is by default connected via a UART device (<code>/dev/ttyAMA0</code> on the RPi4) and needs to be enabled through <code>btattach</code>:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{ pkgs, ... }:
{
  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>}}
== Camera ==
For the camera to work, you will need to add the following code to your configuration.nix:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{ config, pkgs, lib, ... }:
{
  boot.loader.raspberryPi.enable = true;
  # Set the version depending on your raspberry pi.
  boot.loader.raspberryPi.version = 3;
  # We need uboot
  boot.loader.raspberryPi.uboot.enable = true;
  # These two parameters are the important ones to get the
  # camera working. These will be appended to /boot/config.txt.
  boot.loader.raspberryPi.firmwareConfig = ''
    start_x=1
    gpu_mem=256
  '';
}
</nowiki>}}
{{note| A reboot is required to load the new firmware configuration.}}
To make the camera available as v4l device under <code>/dev/video0</code> the <code>bcm2835-v4l2</code> kernel module need to be loaded. This can be done by adding the following code to your configuration.nix:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{ config, pkgs, lib, ... }:
{
  boot.kernelModules = [ "bcm2835-v4l2" ];
}
</nowiki>}}
== Binary Cache ==
== Binary Cache ==


Line 190: Line 258:
| AArch64
| AArch64
|}
|}
== Kernel selection ==
By default NixOS uses the official Linux kernel released by kernel.org (a "mainline" kernel, e.g. <code>pkgs.linuxPackages</code>). This works fine on a Raspberry Pi, and is the better-tested option.
It is also possible to use a kernel released by the Raspberry Pi Foundation (a "vendor" kernel, e.g. <code>pkgs.linuxPackages_rpi3</code>). This may be preferable if you're using an add-on board that the mainline kernel does not have drivers for.
You can select your kernel by setting <code>boot.kernelPackages</code>.


== Notes about the boot process ==
== Notes about the boot process ==


The custom bootloader, part of the Raspberry Pi firmware, is abstracted away for NixOS by making it boot U-Boot instead.
The Raspberry Pi's stage 1 bootloader (in ROM) loads the stage 2 bootloader (bootcode.bin) from the first VFAT partition on the SD card. The NixOS aarch64 SD card image includes a VFAT partition (labelled <code>FIRMWARE</code>) with the stage 2 bootloader and configuration that loads U-Boot. U-Boot then continues from the second partition (labelled <code>NIXOS_SD</code>).
 
It takes approximately 1 minute to boot a Pi 3B.
 
There are 2 primary options for booting a Raspberry Pi:
 
=== Boot option 1: <code>boot.loader.generic-extlinux-compatible</code> ===
 
This configuration is the most similar to the way that NixOS works on other devices. The downside is that NixOS won't attempt to manage anything associated with the first and second stage bootloaders (e.g. config.txt).
 
You can feel better about this by thinking about this configuration as similar to BIOS settings.
 
<syntaxhighlight lang="nix">
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
</syntaxhighlight>
 
=== Boot option 2: <code>boot.loader.raspberryPi</code> ===
 
{{warning| This option has been deprecated in https://github.com/NixOS/nixpkgs/pull/241534}}
 
This configuration assumes that the VFAT firmware partition is mounted to /boot. If it isn't, options like <code>boot.loader.raspberryPi.firmwareConfig</code> will write their configuration to the wrong partition and have no effect.


U-Boot gives us the ability to provide a generation selection menu during the boot process, in addition to storing the boot files on the main partition, rather than on the firmware partition.
<syntaxhighlight lang="nix">
boot.loader.grub.enable = false;
boot.loader.raspberryPi.enable = true;
boot.loader.raspberryPi.uboot.enable = true;
</syntaxhighlight>


=== Raspberry Pi (all versions) ===
=== Raspberry Pi (all versions) ===
Line 202: Line 303:


Using the 3.3v serial port via the pin headers (exact location depends on hardware version) will get u-boot output and, when configured, a Linux kernel console.
Using the 3.3v serial port via the pin headers (exact location depends on hardware version) will get u-boot output and, when configured, a Linux kernel console.
== Device trees ==
Raspberry Pi add-on hardware often requires a device tree overlay. On other OSes this is usually set up using a <code>dtoverlay=</code> option in config.txt on the firmware partition. This approach can be made to work on NixOS with some combination of bootloader and kernel, but it may be easier and more explicit to use NixOS' <code>hardware.deviceTree</code> option to compile the overlay directly into the device tree.
A device tree config looks something like this:
<syntaxhighlight lang="nix">
hardware.deviceTree = {
    enable = true;
    overlays = [
      {
        name = "hifiberry-dacplus";
        dtsText = ''
/dts-v1/;
/plugin/;
/ {
      compatible = "brcm,bcm2835";
// ... etc.
'';
      };
    ];
  };
</syntaxhighlight>
This will apply the overlay to all <code>.dtb</code> files with a matching <code>compatible</code> line.
After rebooting you can check if the overlay has been applied by looking for it in the output of <code>dtc --sort /proc/device-tree</code>.
dtoverlay may fail with <code>FDT_ERR_NOTFOUND</code> on some Raspberry Pi device tree overlays. In this case dtmerge should be used instead. There is a Nix overlay to use dtmerge for applying device tree overlays: https://github.com/NixOS/nixos-hardware/blob/429f232fe1dc398c5afea19a51aad6931ee0fb89/raspberry-pi/4/apply-overlays-dtmerge.nix


== Troubleshooting ==
== Troubleshooting ==
Line 207: Line 339:
=== Power issues ===
=== Power issues ===


Especially with the newer power-hungry Raspberry Pi families (3, 4), it is important to have a [https://www.raspberrypi.org/documentation/hardware/raspberrypi/power/README.md sufficient enough power supply] or ''weirdness'' may happen. Weirdness may include:
Especially with the power-hungry Raspberry Pi 3, it is important to have a [https://www.raspberrypi.org/documentation/hardware/raspberrypi/power/README.md sufficient enough power supply] or unexpected behaviour may occur; this may include:


* Lightning bolt on HDMI output "breaking" the display.
* Lightning bolt on HDMI output "breaking" the display.
Line 214: Line 346:
* Random hangs
* Random hangs


This problem is a hard problem. It is caused by the Raspberry Pi warning about power issues, but the current drivers (as of  
This is a hard problem. It is caused by the Raspberry Pi warning about power issues, but the current drivers (as of  
Linux 4.14) have a hard time dealing with it properly. If the power supply is rated properly AND the cable is not incurring too much power losses, it may be required to disable the lightning bolt indicator so the display driver isn't messed up.<ref>https://logs.nix.samueldr.com/nixos/2017-12-20#1513784657-1513784714;</ref> The lightning bolt indicator can be disabled by adding the line <code>avoid_warnings=1</code> in config.txt<ref>https://www.raspberrypi.org/documentation/configuration/config-txt/README.md</ref>
Linux 4.14) have a hard time dealing with it properly. If the power supply is rated properly AND the cable is not incurring too much power losses, it may be required to disable the lightning bolt indicator so the display driver isn't messed up.<ref>https://logs.nix.samueldr.com/nixos/2017-12-20#1513784657-1513784714;</ref> The lightning bolt indicator can be disabled by adding the line <code>avoid_warnings=1</code> in config.txt<ref>https://www.raspberrypi.org/documentation/configuration/config-txt/README.md</ref>


{{note|A ''properly rated'' USB power supply, AND a good cable are necessary. The cable has to be short enough to not incur power losses through the length. Do note that thin and cheap cables usually have thinner copper wires, which in turn accentuates power losses.}}
{{note|A ''properly rated'' USB power supply, AND a good cable are necessary. The cable has to be short enough to not incur power losses through the length. Do note that thin and cheap cables usually have thinner copper wires, which in turn accentuates power losses.}}
===WiFi / WLAN===
For a possible solution to 802.11 wireless connectivity issues, see: https://github.com/NixOS/nixpkgs/issues/82462#issuecomment-604634627
===HDMI===
HDMI issues have been observed on the 18.09 AArch64 image. The display would hang on "Starting Kernel...", then act as if the HDMI cable was unplugged. Re-plugging the HDMI cable after boot fixed the issue, as did a different monitor and HDMI cable.
==== Early boot messages ====
To show boot messages from initrd with the mainline kernel, add this to <code>configuration.nix</code>.
<syntaxhighlight lang=nix>
{
  boot.initrd.kernelModules = [ "vc4" "bcm2835_dma" "i2c_bcm2835" ];
}
</syntaxhighlight>
=== Raspberry Pi 3B+ HDMI output issues ===
As of 2019/08/19, the u-boot build and kernel build can disagree about the name of the dtb file for the Raspberry Pi 3B+. This happens because the upstream filename has changed, and the built u-boot has hardcoded expectations for the filename to load.
For now, do not use <tt>linuxPackages_latest</tt>, use the default <tt>linuxPackages</tt> which is the latest LTS, 4.19, which is known to be compatible.
See {{issue|66960}}.


===Additional Troubleshooting===
===Additional Troubleshooting===

Latest revision as of 21:55, 1 August 2024

Raspberry Pi Family
A Raspberry Pi 3 with enclosure.
Raspberry Pi
Architecture ARMv6
Raspberry Pi 2
Architecture ARMv7
Raspberry Pi 3
Architecture AArch64 + ARMv7
Raspberry Pi 4
Architecture AArch64 + ARMv7

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

Only the Raspberry Pi 3 Family is supported upstream, with the AArch64 effort. Other Raspberry Pis are part of @dezgeg's porting efforts to ARMv6 and ARMv7.

The Linux kernel in use, except for the Raspberry Pi 1 family, is the mainline Linux kernel, and not the Raspberry Pi Foundation's fork. This could reduce compatibility with some add-on boards or third-party libraries[expanded explanation needed].

The following table is intended to be updated by the NixOS contributors with the current status of the boards. For a list of products, see the Products Archive.

Board name Architecture Support
Raspberry Pi 1
Raspberry Pi 1 Model B armv6 C
Raspberry Pi 1 Model A+ C*
Raspberry Pi 1 Model B+ C
Raspberry Pi Zero C*
Raspberry Pi Zero W C
Raspberry Pi 2
Raspberry Pi 2 Model B armv7 C
Raspberry Pi 3
Raspberry Pi 3 Model B AArch64
+ armv7
YES
Raspberry Pi 3 Model B+ YES
Raspberry Pi 3 Model A+ ?
Raspberry Pi 4
Raspberry Pi 4 Model B AArch64
+ armv7
YES
Raspberry Pi 400
Raspberry Pi 400 AArch64
+ armv7
Yes (only with kernel >= 6.1)

Support

  • YES: Supported architecture by Nixpkgs downstream and tested to be working.
  • C: Community supported, and tested to be working.
  • C*: Community supported, unverified but should be working.
  • ? : Unverified, unknown if it will work.

The Raspberry Pi 3 Family is only supported as AArch64. Use as armv7 is community supported.

Board-specific installation notes

First follow the generic installation steps to get the installer image and install using the installation and configuration steps.

Raspberry Pi (1)

The ARMv6 image boots out-of-the-box.

Raspberry Pi 2

The ARMv7 image should boot out-of-the-box, though the author hasn't personally tested this.

Raspberry Pi 3 / 3B+

Both the AArch64 and ARMv7 images boot out-of-the-box. Using the 64-bit AArch64 image is highly recommended, as the availability of binaries is much better and allows the use of the 64-bit instruction set.

For the UART console, edit /extlinux/extlinux.conf on the boot partition of the SD card to set console=ttyS1,115200n8 in the kernel boot parameters, and use the following GPIO Pins with an USB-TTL connector:

GND         - 3rd in top row, black cable
GPIO 14 TXD - 4th in top row, white cable
GPIO 15 RXD - 5th in top row, green cable

Use nix-shell -p screen --run "screen /dev/ttyUSB0 115200" to connect to the console.

Note: The mainline kernel (tested with nixos kernel 4.18.7) does not include support for cpu frequency scaling on the Raspberry Pi. To get higher clock speed, set force_turbo=1 in /boot/config.txt
{
  hardware.enableRedistributableFirmware = true;
  networking.wireless.enable = true;
}

HDMI output issue with kernel 5.4 (NixOS 20.03 or NixOS unstable)

(Unverified for 5.5 or 5.6)

Some users have reported that the 5.4 kernel "hung at Starting kernel..." #82455. In all cases where it was possible to investigate, it was found that the device did boot, but that the HDMI out didn't function as expected.

It looks like it may be a setup-dependent issue, as a 20.03 image with 5.4 was verified as working.

If your setup is having the issue, first report on #82455 with the Raspberry Pi model (important to note whether it is a plus or non-plus) and the kind of display used with the HDMI out, including whether it is using adapters or not.

Then, you can work around the issue by configuring your system to use the 4.19 kernel (previous LTS) using one of the following tricks.

  1. Use the serial console to configure the system, and nixos-rebuild boot it.
  2. Use a 19.09 image, specify the kernel in its configuration and upgrade to 20.03
  3. Boot the image, poweroff blindly using a keyboard, edit on another computer /home/nixos/.ssh/authorized_keys from the SD to add your key file, chmod as 600, unmount, boot the Raspberry Pi and find it on your network by some means.
{
  boot.kernelPackages = pkgs.linuxPackages_4_19;
}

Raspberry Pi 4

See NixOS on ARM/Raspberry Pi 4

Raspberry Pi 5

See NixOS on ARM/Raspberry Pi 5

Audio

In addition to the usual config, it might be required to enable audio support explicitly in the firmwareConfig.

/etc/nixos/configuration.nix
  sound.enable = true;
  hardware.pulseaudio.enable = true;

  boot.loader.raspberryPi.firmwareConfig = ''
    dtparam=audio=on
  '';

Serial console

Your configuration.nix will need to add console=ttyS1,115200n8 to the boot.kernelParams configuration to use the serial console.

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
  boot.kernelParams = [
    "console=ttyS1,115200n8"
  ];
}

If the Raspberry Pi downstream kernel is used the serial interface is named serial0 instead.

Bluetooth

The bluetooth controller is by default connected via a UART device (/dev/ttyAMA0 on the RPi4) and needs to be enabled through btattach:

/etc/nixos/configuration.nix
{ pkgs, ... }:
{
  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";
    };
  };
}

Camera

For the camera to work, you will need to add the following code to your configuration.nix:

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
  boot.loader.raspberryPi.enable = true;
  # Set the version depending on your raspberry pi. 
  boot.loader.raspberryPi.version = 3;
  # We need uboot
  boot.loader.raspberryPi.uboot.enable = true;
  # These two parameters are the important ones to get the
  # camera working. These will be appended to /boot/config.txt.
  boot.loader.raspberryPi.firmwareConfig = ''
    start_x=1
    gpu_mem=256
  '';
}
Note: A reboot is required to load the new firmware configuration.

To make the camera available as v4l device under /dev/video0 the bcm2835-v4l2 kernel module need to be loaded. This can be done by adding the following code to your configuration.nix:

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
  boot.kernelModules = [ "bcm2835-v4l2" ];
}

Binary Cache

Depending on the architecture used, binary caches availability varies. Binary caches instructions are on the main NixOS on ARM page. The following table describes the architectures supported by each board.

Raspberry Pi 1 armv6
Raspberry Pi 2 armv7
Raspberry Pi 3 armv7
AArch64
Raspberry Pi 4 armv7
AArch64

Kernel selection

By default NixOS uses the official Linux kernel released by kernel.org (a "mainline" kernel, e.g. pkgs.linuxPackages). This works fine on a Raspberry Pi, and is the better-tested option.

It is also possible to use a kernel released by the Raspberry Pi Foundation (a "vendor" kernel, e.g. pkgs.linuxPackages_rpi3). This may be preferable if you're using an add-on board that the mainline kernel does not have drivers for.

You can select your kernel by setting boot.kernelPackages.

Notes about the boot process

The Raspberry Pi's stage 1 bootloader (in ROM) loads the stage 2 bootloader (bootcode.bin) from the first VFAT partition on the SD card. The NixOS aarch64 SD card image includes a VFAT partition (labelled FIRMWARE) with the stage 2 bootloader and configuration that loads U-Boot. U-Boot then continues from the second partition (labelled NIXOS_SD).

It takes approximately 1 minute to boot a Pi 3B.

There are 2 primary options for booting a Raspberry Pi:

Boot option 1: boot.loader.generic-extlinux-compatible

This configuration is the most similar to the way that NixOS works on other devices. The downside is that NixOS won't attempt to manage anything associated with the first and second stage bootloaders (e.g. config.txt).

You can feel better about this by thinking about this configuration as similar to BIOS settings.

boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;

Boot option 2: boot.loader.raspberryPi

Warning: This option has been deprecated in https://github.com/NixOS/nixpkgs/pull/241534

This configuration assumes that the VFAT firmware partition is mounted to /boot. If it isn't, options like boot.loader.raspberryPi.firmwareConfig will write their configuration to the wrong partition and have no effect.

boot.loader.grub.enable = false;
boot.loader.raspberryPi.enable = true;
boot.loader.raspberryPi.uboot.enable = true;

Raspberry Pi (all versions)

USB keyboards and HDMI displays should work, though some issues have been reported (see Troubleshooting below).

Using the 3.3v serial port via the pin headers (exact location depends on hardware version) will get u-boot output and, when configured, a Linux kernel console.

Device trees

Raspberry Pi add-on hardware often requires a device tree overlay. On other OSes this is usually set up using a dtoverlay= option in config.txt on the firmware partition. This approach can be made to work on NixOS with some combination of bootloader and kernel, but it may be easier and more explicit to use NixOS' hardware.deviceTree option to compile the overlay directly into the device tree.

A device tree config looks something like this:

hardware.deviceTree = {
    enable = true;
    overlays = [
      {
        name = "hifiberry-dacplus";
        dtsText = ''
/dts-v1/;
/plugin/;
/ {
       compatible = "brcm,bcm2835";

// ... etc.
'';
      };
    ];
  };

This will apply the overlay to all .dtb files with a matching compatible line.

After rebooting you can check if the overlay has been applied by looking for it in the output of dtc --sort /proc/device-tree.

dtoverlay may fail with FDT_ERR_NOTFOUND on some Raspberry Pi device tree overlays. In this case dtmerge should be used instead. There is a Nix overlay to use dtmerge for applying device tree overlays: https://github.com/NixOS/nixos-hardware/blob/429f232fe1dc398c5afea19a51aad6931ee0fb89/raspberry-pi/4/apply-overlays-dtmerge.nix

Troubleshooting

Power issues

Especially with the power-hungry Raspberry Pi 3, it is important to have a sufficient enough power supply or unexpected behaviour may occur; this may include:

  • Lightning bolt on HDMI output "breaking" the display.
  • Screen switching back to u-boot text
    • Fixable temporarily when power is sufficient by switching VT (alt+F2 / alt+F1)
  • Random hangs

This is a hard problem. It is caused by the Raspberry Pi warning about power issues, but the current drivers (as of Linux 4.14) have a hard time dealing with it properly. If the power supply is rated properly AND the cable is not incurring too much power losses, it may be required to disable the lightning bolt indicator so the display driver isn't messed up.[1] The lightning bolt indicator can be disabled by adding the line avoid_warnings=1 in config.txt[2]

Note: A properly rated USB power supply, AND a good cable are necessary. The cable has to be short enough to not incur power losses through the length. Do note that thin and cheap cables usually have thinner copper wires, which in turn accentuates power losses.

WiFi / WLAN

For a possible solution to 802.11 wireless connectivity issues, see: https://github.com/NixOS/nixpkgs/issues/82462#issuecomment-604634627

HDMI

HDMI issues have been observed on the 18.09 AArch64 image. The display would hang on "Starting Kernel...", then act as if the HDMI cable was unplugged. Re-plugging the HDMI cable after boot fixed the issue, as did a different monitor and HDMI cable.

Early boot messages

To show boot messages from initrd with the mainline kernel, add this to configuration.nix.

{
  boot.initrd.kernelModules = [ "vc4" "bcm2835_dma" "i2c_bcm2835" ];
}

Raspberry Pi 3B+ HDMI output issues

As of 2019/08/19, the u-boot build and kernel build can disagree about the name of the dtb file for the Raspberry Pi 3B+. This happens because the upstream filename has changed, and the built u-boot has hardcoded expectations for the filename to load.

For now, do not use linuxPackages_latest, use the default linuxPackages which is the latest LTS, 4.19, which is known to be compatible.

See #66960.

Additional Troubleshooting

Additional troubleshooting information may be found at elinux.org.