Enabling Raspberry Pi 5 Onboard Wi-Fi using Buildroot External Tree

The Raspberry Pi 5 features a built-in wireless module based on the Cypress CYW43455, which connects to the main processor via an SDIO interface. This hardware provides wireless capabilities that make the WLAN interface one of the board’s most powerful and versatile features. It supports a wide range of use cases, from remote monitoring systems and IoT applications to portable media centers and wireless networking setups. When designing a device that needs to connect to the internet (WAN) or operate within a local network (LAN), the onboard Wi-Fi removes the need for Ethernet cables, resulting in a cleaner and more flexible setup—especially valuable in constrained spaces or field deployments where wiring is impractical. This post walks through the process of setting up a br2-external tree and enabling the Raspberry Pi 5’s WLAN interface from scratch using Buildroot, allowing developers to fully leverage wireless networking in embedded projects. Buildroot External Tree As work with Buildroot progresses, it becomes increasingly beneficial to take advantage of its customization capabilities. One powerful approach is to use a Buildroot External Tree. By setting up an external tree directory, custom board configurations and packages are kept separate from the core Buildroot source. This aligns with the recommended development architecture and makes it significantly easier to switch between different Buildroot versions without losing customizations. It streamlines version upgrades, improves maintainability, and encourages a cleaner, modular development workflow. Recommended directory structure The Buildroot official documentation recommends the following structure for storing board-specific customizations. When placed outside the main Buildroot source tree, this is referred to as a br2-external tree. +-- board/ | +-- / | +-- linux.config | +-- busybox.config | +-- | +-- post_build.sh | +-- post_image.sh | +-- rootfs_overlay/ | | +-- etc/ | | +-- | +-- patches/ | +-- foo/ | | +-- | +-- libbar/ | +-- | +-- configs/ | +-- _defconfig | +-- package/ | +-- package1/ | | +-- Config.in | | +-- package1.mk | +-- package2/ | +-- Config.in | +-- package2.mk | +-- Config.in +-- external.mk +-- external.desc A valid br2-external tree must include at least three essential files, which define the external tree and its customizations: external.desc external.mk Config.in The external.desc file contains metadata about the br2-external tree and is required for Buildroot to properly recognize and integrate the external directory. It supports two keywords: name (mandatory): defines the name of the external tree. Buildroot uses this to create a variable called BR2_EXTERNAL_$(NAME)_PATH, which holds the absolute path to the external tree. The name must consist of ASCII characters only. desc (optional): provides a short description (recommended a maximum of 40 characters) for the external tree. This description is available within Buildroot as the variable BR2_EXTERNAL_$(NAME)_DESC. To create a basic br2-external tree in the home folder and define its external.desc file, the following can be used: mkdir ~/br2-external-tree echo "name: DEV_TO_TREE" > ~/br2-external-tree/external.desc external.mk file includes the Makefiles of all custom packages so that Buildroot knows how to build them. This file can be created by running: cat > ~/br2-external-tree/external.mk ~/br2-external-tree/package/brcmfmac-firmware/Config.in ~/br2-external-tree/package/brcmfmac-firmware/brcmfmac-firmware.mk ~/br2-external-tree/Config.in Raspberry Pi 5 Customizations. WPA Supplicant and Wireless Interface Setup Jumping into the user space, WPA Supplicant can be used to manage the wireless interface. This package in located under Target packages -> Networking applications after running make menuconfig from output folder. The following options should be enabled: BR2_PACKAGE_WPA_SUPPLICANT=y BR2_PACKAGE_WPA_SUPPLICANT_WEXT=y BR2_PACKAGE_WPA_SUPPLICANT_CLI=y BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y Additionally, enable the iw and wireless-regdb packages from the same section: BR2_PACKAGE_IW=y BR2_PACKAGE_WIRELESS_REGDB=y Proceeding to the configuration of the wireless interface, it will be set up to obtain an IP address from a wireless access point using DHCP, with WPA Supplicant handling the connection. As before, br2-external tree will be used to store this configuration under the rootfs_overlay folder. mkdir -p ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/network cat > ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/network/interfaces ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/wpa_supplicant.conf ~/br2-external-tr

Apr 12, 2025 - 22:08
 0
Enabling Raspberry Pi 5 Onboard Wi-Fi using Buildroot External Tree

The Raspberry Pi 5 features a built-in wireless module based on the Cypress CYW43455, which connects to the main processor via an SDIO interface. This hardware provides wireless capabilities that make the WLAN interface one of the board’s most powerful and versatile features. It supports a wide range of use cases, from remote monitoring systems and IoT applications to portable media centers and wireless networking setups.

When designing a device that needs to connect to the internet (WAN) or operate within a local network (LAN), the onboard Wi-Fi removes the need for Ethernet cables, resulting in a cleaner and more flexible setup—especially valuable in constrained spaces or field deployments where wiring is impractical.

This post walks through the process of setting up a br2-external tree and enabling the Raspberry Pi 5’s WLAN interface from scratch using Buildroot, allowing developers to fully leverage wireless networking in embedded projects.

Buildroot External Tree

As work with Buildroot progresses, it becomes increasingly beneficial to take advantage of its customization capabilities. One powerful approach is to use a Buildroot External Tree. By setting up an external tree directory, custom board configurations and packages are kept separate from the core Buildroot source. This aligns with the recommended development architecture and makes it significantly easier to switch between different Buildroot versions without losing customizations. It streamlines version upgrades, improves maintainability, and encourages a cleaner, modular development workflow.

Recommended directory structure

The Buildroot official documentation recommends the following structure for storing board-specific customizations. When placed outside the main Buildroot source tree, this is referred to as a br2-external tree.

+-- board/
|       +-- /
|           +-- linux.config
|           +-- busybox.config
|           +-- 
|           +-- post_build.sh
|           +-- post_image.sh
|           +-- rootfs_overlay/
|           |   +-- etc/
|           |   +-- 
|           +-- patches/
|               +-- foo/
|               |   +-- 
|               +-- libbar/
|                   +-- 
|
+-- configs/
|   +-- _defconfig
|
+-- package/
|       +-- package1/
|       |    +-- Config.in
|       |    +-- package1.mk
|       +-- package2/
|           +-- Config.in
|           +-- package2.mk
|
+-- Config.in
+-- external.mk
+-- external.desc

A valid br2-external tree must include at least three essential files, which define the external tree and its customizations:

  • external.desc

  • external.mk

  • Config.in

The external.desc file contains metadata about the br2-external tree and is required for Buildroot to properly recognize and integrate the external directory. It supports two keywords:

  • name (mandatory): defines the name of the external tree. Buildroot uses this to create a variable called BR2_EXTERNAL_$(NAME)_PATH, which holds the absolute path to the external tree. The name must consist of ASCII characters only.

  • desc (optional): provides a short description (recommended a maximum of 40 characters) for the external tree. This description is available within Buildroot as the variable BR2_EXTERNAL_$(NAME)_DESC.

To create a basic br2-external tree in the home folder and define its external.desc file, the following can be used:

mkdir ~/br2-external-tree
echo "name: DEV_TO_TREE" > ~/br2-external-tree/external.desc

external.mk file includes the Makefiles of all custom packages so that Buildroot knows how to build them. This file can be created by running:

cat > ~/br2-external-tree/external.mk << 'EOF'
include $(sort $(wildcard $(BR2_EXTERNAL_DEV_TO_TREE_PATH)/package/*/*.mk))
EOF

Note: BR2_EXTERNAL_DEV_TO_TREE_PATH refers to the name set in external.desc file earlier.

Config.in file declares the configuration options for custom packages, allowing them to appear in Buildroot’s menuconfig interface. A typical Config.in might look like this:

source "$BR2_EXTERNAL_DEV_TO_TREE_PATH/package/package1/Config.in"
source "$BR2_EXTERNAL_DEV_TO_TREE_PATH/package/package2/Config.in"

For now, an empty file will do the job, as we will come back to it later:

touch ~/br2-external-tree/Config.in

Build Configuration for Raspberry Pi 5

With the basis of the br2-external tree set, the next objective is to configure Builroot building system, using the default configuration for Rasberry Pi 5 board and passing the br2-external tree path in BR2_EXTERNAL variable (refer to this post to check on how to download and install Buildroot):

mkdir ~/output && cd ~/output
make O=$PWD -C /var/buildroot-2024.11.1 \
BR2_EXTERNAL=~/br2-external-tree raspberrypi5_defconfig

This assumes Buildroot version 2024.11.1 is installed in the /var directory.

Linux Kernel configuration

Device Tree

WLAN interface for the Raspberry Pi 5 is defined in two separate Device Tree Source (DTS) files included in the default configuration for Raspberry Pi 5 board in the Linux Kernel source. These files are:

If you're unfamiliar with DTS files, one of my previous posts provides a brief introduction.

The SDIO interface used by the onboard Wi-Fi is described in the following DTS entry:

sdio2: mmc@1100000 {
    compatible = "brcm,bcm2712-sdhci";
    reg = <0x10 0x01100000  0x0 0x260>,
          <0x10 0x01100400  0x0 0x200>;
    reg-names = "host", "cfg";
    interrupts = ;
    clocks = <&clk_emmc2>;
    sdhci-caps-mask = <0x0000C000 0x0>;
    sdhci-caps = <0x0 0x0>;
    supports-cqe;
    mmc-ddr-3_3v;
    status = "disabled";
};

This interface is later referenced and enabled in another section of the DTS, which also includes the WLAN device node:

&sdio2 {
    pinctrl-0 = <&sdio2_30_pins>;
    pinctrl-names = "default";
    bus-width = <4>;
    vmmc-supply = <&wl_on_reg>;
    sd-uhs-ddr50;
    non-removable;
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;

    wifi: wifi@1 {
        reg = <1>;
        compatible = "brcm,bcm4329-fmac";
        local-mac-address = [00 00 00 00 00 00];
    };
};

Device drivers

To ensure the wireless module on the Raspberry Pi 5 functions correctly, the Linux Kernel must be properly configured. Specifically, the Kernel should include support for both the generic wireless stack and the Raspberry Pi 5’s Broadcom-based hardware.

The following options should be enabled in the Kernel configuration by running make linux-menuconfig inside output folder:

[*] Networking support --->
  [*] Wireless --->
     cfg80211 - wireless configuration API
    [*] enable powersave by default
    [*] support CRDA
    [*] cfg80211 wireless extensions compatibility

Device Drivers --->
  [*] Network device support --->
    [*] Wireless LAN ---> 
       [*] Broadcom devices
        Broadcom FullMAC WLAN driver
       [*] SDIO bus interface support for FullMAC driver

All other Kernel options were left at their default values.

Firmware Custom Package

Many wireless network interfaces require firmware to be loaded by the Kernel at runtime. This is the case for the CYW43455 used on the Raspberry Pi 5. However, this firmware is not available in any of Buildroot’s in-tree packages. To solve this, br2-external tree feature can be leveraged to create a custom package that fetches the firmware from its official repository and installs it in the appropriate location within the target root filesystem

Creating the Custom Package

First, create a folder to hold the files that describe your custom package (i.e. .mk and Config.infiles):

mkdir -p ~/br2-external-tree/package/brcmfmac-firmware

Create the Config.in file to define how this package appears in Buildroot's menuconfig and what option name it uses:

cat > ~/br2-external-tree/package/brcmfmac-firmware/Config.in << 'EOF' 
config BR2_PACKAGE_BRCMFMAC_FIRMWARE
  bool "BRCMFMAC Firmware"
  default n
  help
    Downloads and install CYW43455 firmware from Linux Kernel source
EOF

Next, define the .mk file to tell Buildroot where to fetch the firmware and how to install it under /lib/firmware/brcm:

cat > ~/br2-external-tree/package/brcmfmac-firmware/brcmfmac-firmware.mk << 'EOF' 
BRCMFMAC_FIRMWARE_VERSION := 20250311
BRCMFMAC_FIRMWARE_SOURCE := linux-firmware-$(BRCMFMAC_FIRMWARE_VERSION).tar.gz
BRCMFMAC_FIRMWARE_SITE := https://web.git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/snapshot

define BRCMFMAC_FIRMWARE_INSTALL_TARGET_CMDS
  $(INSTALL) -D -m 0644 $(@D)/cypress/cyfmac43455-sdio.bin $(TARGET_DIR)/lib/firmware/brcm/brcmfmac43455-sdio.bin

  $(INSTALL) -D -m 0644 $(@D)/cypress/cyfmac43455-sdio.clm_blob $(TARGET_DIR)/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob

  $(INSTALL) -D -m 0644 $(@D)/brcm/brcmfmac43455-sdio.raspberrypi,4-model-b.txt $(TARGET_DIR)/lib/firmware/brcm/brcmfmac43455-sdio.txt

  $(INSTALL) -D -m 0644 $(@D)/cypress/cyfmac43455-sdio.bin $(TARGET_DIR)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.bin

  $(INSTALL) -D -m 0644 $(@D)/cypress/cyfmac43455-sdio.clm_blob $(TARGET_DIR)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.clm_blob

  $(INSTALL) -D -m 0644 $(@D)/brcm/brcmfmac43455-sdio.raspberrypi,4-model-b.txt $(TARGET_DIR)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.txt
endef

$(eval $(generic-package))
EOF

Registering the Package

Finally, add an entry in the top-level Config.in file of your br2-external tree so the package appears in the menuconfig:

cat > ~/br2-external-tree/Config.in << 'EOF' 
menu "Raspberry Pi 5 Customizations"
source "$BR2_EXTERNAL_DEV_TO_TREE_PATH/package/brcmfmac-firmware/Config.in"
endmenu
EOF

And enable the option just that had just been created:

cd ~/output
make menuconfig

The new option should be located in External options -> Raspberry Pi 5 Customizations.

WPA Supplicant and Wireless Interface Setup

Jumping into the user space, WPA Supplicant can be used to manage the wireless interface. This package in located under Target packages -> Networking applications after running make menuconfig from output folder. The following options should be enabled:

BR2_PACKAGE_WPA_SUPPLICANT=y
BR2_PACKAGE_WPA_SUPPLICANT_WEXT=y
BR2_PACKAGE_WPA_SUPPLICANT_CLI=y
BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y

Additionally, enable the iw and wireless-regdb packages from the same section:

BR2_PACKAGE_IW=y
BR2_PACKAGE_WIRELESS_REGDB=y

Proceeding to the configuration of the wireless interface, it will be set up to obtain an IP address from a wireless access point using DHCP, with WPA Supplicant handling the connection. As before, br2-external tree will be used to store this configuration under the rootfs_overlay folder.

mkdir -p ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/network
cat > ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/network/interfaces << 'EOF'
auto lo
iface lo inet loopback

auto wlan0
iface wlan0 inet dhcp
   pre-up wpa_supplicant -B -Dnl80211,wext -i wlan0 -c /etc/wpa_supplicant.conf
   post-down killall -q wpa_supplicant
EOF

As seen above, WPA Supplicant is expecting a configuration file, which should be stored inside /etc folder. This file tells WPA Supplicant how to connect to your Wi-Fi network. Create it by running:

cat > ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/wpa_supplicant.conf << 'EOF'
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=BR

network={
ssid=
psk=
}
EOF

❗ Make sure to edit this file passing the SSID and the password for the desired network.

Post-Boot Driver Initialization

During the Kernel configuration CYW43455 device drivers were configured to be compiled as modules. The reason for that is that they cannot be loaded before the root filesystem is mounted, as it is expected that the Kernel to load the firmware for the CYW43455 hardware, which is is stored in /lib/firmware/brcm. To ensure the drivers load properly at boot, an init script that loads the modules once the system is up could be created as follows:

mkdir -p ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/init.d
cat > ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/init.d/S35wlan_modules << 'EOF'
#!/bin/sh

install_wlan_modules() {
  modprobe brcmutil || return 1
  modprobe brcmfmac || return 1
  sleep 5
  return 0
}

uninstall_wlan_modules() {
  rmmod brcmfmac || return 1
  rmmod brcmutil || return 1
  return 0
}

case "$1" in
  start)
    printf "Installing wlan modules... "
    install_wlan_modules
    [ $? -eq 0 ] && echo "OK" || echo "FAIL"
    ;;
  stop)
    printf "Uninstalling wlan modules... "
    uninstall_wlan_modules
    [ $? -eq 0 ] && echo "OK" || echo "FAIL"
    ;;
  restart)
    printf "Uninstalling wlan modules... "
    uninstall_wlan_modules
    [ $? -eq 0 ] && echo "OK" || echo "FAIL"

    printf "Installing wlan modules... "
    install_wlan_modules
    [ $? -eq 0 ] && echo "OK" || echo "FAIL"
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
    ;;
esac

exit $?
EOF

Make sure to add execution permission for the script we just created:

chmod +x ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/init.d/S35wlan_modules 

Configuring the Root Filesystem Overlay

All is there left to do is to configure the BR2_ROOTFS_OVERLAY so Buildroot knows where to find the settings that were just created. This option is located under System configuration after running make menuconfig inside output folder.

BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_DEV_TO_TREE_PATH)/board/raspberrypi5/rootfs_overlay"

Once everything is saved, the compilation can be triggered by running make inside output folder.

Flashing the Image to an SD Card

After the compilation is complete without errors, the final binary file will be located in the output/images folder and will be named sdcard.img. This is the file that needs to be written to the SD card to boot the Raspberry Pi board, which can be done by the following (assuming it is enumerated as /dev/sda):

dd if=images/sdcard.img of=/dev/sda status=progress

Conclusion