NixOS on ARM/Raspberry Pi 3: Difference between revisions

From NixOS Wiki
imported>Samueldr
Tobsz (talk | contribs)
m Add missing closing paren.
 
(7 intermediate revisions by 7 users not shown)
Line 43: Line 43:


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]].
{{warning|1=To avoid running out of memory and ''failing'' to build, it is advised to create a swap file (see e.g. [https://wiki.archlinux.org/title/swap#Swap_file_creation]) ''before'' executing <code>nixos-rebuild</code> for the first time.}}


=== Raspberry Pi 3B and 3B+ ===
=== Raspberry Pi 3B and 3B+ ===
Line 48: Line 50:
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.
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 <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:  
For the UART console, edit <code>/extlinux/extlinux.conf</code> on the main partition of the SD card to set <code>console=ttyS1,115200n8</code> in the kernel boot parameters, making sure to replace the existing <code>console=ttyS0,115200n8</code> parameter. Use the following GPIO Pins with an USB-TTL connector:  
<syntaxhighlight>
<syntaxhighlight>
GND        - 3rd in top row, black cable
GND        - 3rd in top row, black cable
Line 66: Line 68:
== Tools ==
== Tools ==


The raspberry tools are available in the <code>raspberrypi-tools</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 ==
== Audio ==
Line 94: Line 96:


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.
=== Early boot ===
Raspberry Pi 3's UART rate is tied to the GPU core frequency, set by default to 400MHz on Raspberry Pi 3 and later. This results in garbled serial output in bootloaders. Setting <code>core_freq=250</code> in <code>config.txt</code> solves this issue (as per [https://forums.raspberrypi.com/viewtopic.php?p=942203#p942203 thread on the Raspberry Pi forum]).
It can be done declaratively as such:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{ config, pkgs, lib, ... }:
{
  boot.loader.raspberryPi = {
    enable = true;
    version = 3;
    firmwareConfig = ''
      core_freq=250
    '';
  };
}
</nowiki>}}
Note that this [https://github.com/RealVNC/raspi-documentation/blob/fc6b4711f91791db7acd19ae743fcfddc9c89546/configuration/config-txt/overclocking.md#overclocking-options may have a negative impact on performance]:
<blockquote>Frequency of the GPU processor core in MHz. It has an impact on CPU performance because it drives the L2 cache and memory bus.</blockquote>


== Bluetooth ==
== Bluetooth ==
Line 149: Line 174:


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.
=== Updating U-Boot ===
[https://github.com/NixOS/nixpkgs/issues/82455#issuecomment-959797355 These steps can be followed to update the platform firmware.]


== Troubleshooting ==
== Troubleshooting ==
Line 215: Line 244:
See {{issue|66960}}.
See {{issue|66960}}.


=== HDMI output issue with kernel 5.4 (NixOS 20.03 or NixOS unstable) ===
=== HDMI output issue with kernel ~6.1 (NixOS 23.05 or NixOS unstable) ===


(Unverified for 5.5 or 5.6)
When using HDMI and hardware acceleration (e.g. Kodi), an application may fail to start and/or crash with a dmesg like:


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.
<pre>
[232195.380745] [drm:vc4_bo_create [vc4]] *ERROR* Failed to allocate from CMA:
[232195.380751] [drm]                        kernel:    432kb BOs (1)
[232195.380755] [drm]                          dumb:  69064kb BOs (14)


It looks like it may be a setup-dependent issue, as a 20.03 image with 5.4 was verified as working.
[306160.152488] cma: cma_alloc: alloc failed, req-size: 142 pages, ret: -16
[306160.152498] [vc_sm_cma_ioctl_alloc]: dma_alloc_coherent alloc of 581632 bytes failed
[306160.152501] [vc_sm_cma_ioctl_alloc]: something failed - cleanup. ret -12
[317686.623989] [drm:vc4_bo_create [vc4]] *ERROR* Failed to allocate from CMA:
[317686.623998] [drm]                          dumb:  74752kb BOs (16)
</pre>


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.
A workaround is to increase the pre-allocated CMA space (which, as of writing, defaults to 65M):


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.
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
 
{ config, pkgs, lib, ... }:
# 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>
{
{
   boot.kernelPackages = pkgs.linuxPackages_4_19;
   boot.kernelParams = ["cma=320M"];
}
}
</syntaxHighlight>
</nowiki>}}
 
===Additional Troubleshooting===
 
Additional troubleshooting information may be found [https://elinux.org/R-Pi_Troubleshooting at elinux.org].


<hr />
For more information see a post in raspberry pi forum<ref>https://forums.raspberrypi.com/viewtopic.php?t=285068</ref> and thios github issue<ref>https://github.com/raspberrypi/linux/issues/3861</ref>.

Latest revision as of 17:31, 20 April 2024

Raspberry Pi 3 Family
A Raspberry Pi 3 with enclosure.
Manufacturer Raspberry Pi Foundation
Architecture AArch64
Bootloader Custom or U-Boot
Boot order SD, USB*
Maintainer
Raspberry Pi 3B
SoC BCM2837
Raspberry Pi 3B+
SoC BCM2837B0

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

The default Linux kernel in use, 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 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.

Warning: To avoid running out of memory and failing to build, it is advised to create a swap file (see e.g. [1]) before executing nixos-rebuild for the first time.

Raspberry Pi 3B and 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 main partition of the SD card to set console=ttyS1,115200n8 in the kernel boot parameters, making sure to replace the existing console=ttyS0,115200n8 parameter. 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" (or nix run nixpkgs#screen -- /dev/ttyUSB0 115200 if you're using nix flakes) 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 with boot.loader.raspberryPi.firmwareConfig
{
  hardware.enableRedistributableFirmware = true;
  networking.wireless.enable = true;
}

Tools

The raspberry tools are available in the libraspberrypi package and include commands like vcgencmd to measure temperature and CPU frequency.

Audio

In addition to the usual config, you will need 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.

Early boot

Raspberry Pi 3's UART rate is tied to the GPU core frequency, set by default to 400MHz on Raspberry Pi 3 and later. This results in garbled serial output in bootloaders. Setting core_freq=250 in config.txt solves this issue (as per thread on the Raspberry Pi forum).

It can be done declaratively as such:

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
  boot.loader.raspberryPi = {
    enable = true;
    version = 3;
    firmwareConfig = ''
      core_freq=250
    '';
  };
}

Note that this may have a negative impact on performance:

Frequency of the GPU processor core in MHz. It has an impact on CPU performance because it drives the L2 cache and memory bus.

Bluetooth

The bluetooth controller is by default connected to the UART device at /dev/ttyAMA0 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" ];
}

Notes about the boot process

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

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.

Updating U-Boot

These steps can be followed to update the platform firmware.

Troubleshooting

Power issues

Especially with the power-hungry Raspberry Pi 3, it is important to have a sufficient enough power supply or weirdness may happen. Weirdness 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 problem 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

In case wlan0 is missing, try overlaying an older firmwareLinuxNonfree confirmed to be working:

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
  nixpkgs.overlays = [
    (self: super: {
      firmwareLinuxNonfree = super.firmwareLinuxNonfree.overrideAttrs (old: {
        version = "2020-12-18";
        src = pkgs.fetchgit {
          url =
            "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git";
          rev = "b79d2396bc630bfd9b4058459d3e82d7c3428599";
          sha256 = "1rb5b3fzxk5bi6kfqp76q1qszivi0v1kdz1cwj2llp5sd9ns03b5";
        };
        outputHash = "1p7vn2hfwca6w69jhw5zq70w44ji8mdnibm1z959aalax6ndy146";
      });
    })
  ];
}

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.

HDMI output issue with kernel ~6.1 (NixOS 23.05 or NixOS unstable)

When using HDMI and hardware acceleration (e.g. Kodi), an application may fail to start and/or crash with a dmesg like:

[232195.380745] [drm:vc4_bo_create [vc4]] *ERROR* Failed to allocate from CMA:
[232195.380751] [drm]                         kernel:    432kb BOs (1)
[232195.380755] [drm]                           dumb:  69064kb BOs (14)

[306160.152488] cma: cma_alloc: alloc failed, req-size: 142 pages, ret: -16
[306160.152498] [vc_sm_cma_ioctl_alloc]: dma_alloc_coherent alloc of 581632 bytes failed
[306160.152501] [vc_sm_cma_ioctl_alloc]: something failed - cleanup. ret -12
[317686.623989] [drm:vc4_bo_create [vc4]] *ERROR* Failed to allocate from CMA:
[317686.623998] [drm]                           dumb:  74752kb BOs (16)

A workaround is to increase the pre-allocated CMA space (which, as of writing, defaults to 65M):

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
  boot.kernelParams = ["cma=320M"];
}

For more information see a post in raspberry pi forum[3] and thios github issue[4].