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

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 calledBR2_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 variableBR2_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.in
files):
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