<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Paulo Fylippe Sell</title>
    <description>The latest articles on Forem by Paulo Fylippe Sell (@pfs).</description>
    <link>https://forem.com/pfs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2937268%2F5b18524a-e756-49c0-a89c-e6674541db96.jpeg</url>
      <title>Forem: Paulo Fylippe Sell</title>
      <link>https://forem.com/pfs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pfs"/>
    <language>en</language>
    <item>
      <title>Monitoring and Controlling CPU Temperature on Linux Systems Using Sysfs</title>
      <dc:creator>Paulo Fylippe Sell</dc:creator>
      <pubDate>Sat, 19 Apr 2025 14:49:52 +0000</pubDate>
      <link>https://forem.com/pfs/monitoring-and-controlling-cpu-temperature-on-raspberry-pi-5-using-buildroot-31gp</link>
      <guid>https://forem.com/pfs/monitoring-and-controlling-cpu-temperature-on-raspberry-pi-5-using-buildroot-31gp</guid>
      <description>&lt;p&gt;Effectively monitoring and managing CPU temperature in embedded systems is crucial to prevent throttling and ensure reliable device performance. The Raspberry Pi 5 features a built-in thermal sensor within its BCM2712 SoC, allowing real-time monitoring of the CPU core temperature. To help manage heat, an active cooler can be used, which typically activates once the CPU reaches a predefined temperature threshold. This article outlines the steps to enable both the thermal sensor and an active cooling system for monitoring and controlling the temperature on a Raspberry Pi 5 board using Buildroot to build the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling the thermal sensor
&lt;/h2&gt;

&lt;p&gt;The thermal sensor on the Raspberry Pi 5 is part of the Adaptive Voltage Scaling (AVS) system, which dynamically adjusts the CPU voltage based on workload and temperature. This mechanism helps reduce both power consumption and heat generation. The sensor is defined in the default Device Tree Source (DTS) file &lt;code&gt;bcm2712.dtsi&lt;/code&gt; found in the Raspberry Pi's &lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm/boot/dts/broadcom/bcm2712.dtsi" rel="noopener noreferrer"&gt;Linux Kernel repository&lt;/a&gt;. The relevant section is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;avs_monitor: avs-monitor@7d542000 {
    compatible = "brcm,bcm2711-avs-monitor",
                    "syscon", "simple-mfd";
    reg = &amp;lt;0x7d542000 0xf00&amp;gt;;
    status = "okay";

    thermal: thermal {
        compatible = "brcm,bcm2711-thermal";
        #thermal-sensor-cells = &amp;lt;0&amp;gt;;
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The device drivers required to enable the thermal sensors listed below are typically included in the default &lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm64/configs/bcm2712_defconfig" rel="noopener noreferrer"&gt;Linux kernel configuration&lt;/a&gt; for the Raspberry Pi 5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONFIG_BCM2711_THERMAL=y
CONFIG_MFD_SYSCON=y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enabling the active cooler
&lt;/h2&gt;

&lt;p&gt;The Raspberry Pi 5 supports an active cooler device that can be connected through a 4-pin a PWM header located on the board’s surface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpvoth4k8qzco3zwc860.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpvoth4k8qzco3zwc860.png" alt="Raspberry Pi 5 official active cooler" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cooler is described in the &lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts" rel="noopener noreferrer"&gt;&lt;code&gt;bcm2712-rpi-5-b.dtsi&lt;/code&gt;&lt;/a&gt; DTS file as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fan: cooling_fan {
    status = "okay";
    compatible = "pwm-fan";
    #cooling-cells = &amp;lt;2&amp;gt;;
    cooling-min-state = &amp;lt;0&amp;gt;;
    cooling-max-state = &amp;lt;3&amp;gt;;
    cooling-levels = &amp;lt;0 75 125 175 250&amp;gt;;
    pwms = &amp;lt;&amp;amp;rp1_pwm1 3 41566 PWM_POLARITY_INVERTED&amp;gt;;
    rpm-regmap = &amp;lt;&amp;amp;rp1_pwm1&amp;gt;;
    rpm-offset = &amp;lt;0x3c&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the &lt;code&gt;cooling_fan&lt;/code&gt; entry status is &lt;code&gt;disabled&lt;/code&gt;, make sure to enable it. Also, make sure to enable the &lt;code&gt;rp1_pwm1&lt;/code&gt; entry in the same DTS file, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;amp;rp1_pwm1 {
    status = "okay";
    pinctrl-0 = &amp;lt;&amp;amp;rp1_pwm1_gpio45&amp;gt;;
    pinctrl-names = "default";
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cooling device can be managed by the generic &lt;code&gt;pwm-fan&lt;/code&gt; driver. The following options should be set in the Linux Kernel configuration to enable the feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONFIG_PWM_RP1=y
CONFIG_SENSORS_PWM_FAN=m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Buildroot configuration
&lt;/h2&gt;

&lt;p&gt;In one of my &lt;a href="https://dev.to/pfs/custom-linux-image-for-raspberry-pi-5-a-guide-with-buildroot-bp3"&gt;previous posts&lt;/a&gt;, I walked through the process of downloading and setting up the Buildroot build system.&lt;/p&gt;

&lt;p&gt;Assuming that &lt;code&gt;Buildroot 2014-11-1&lt;/code&gt; was installed in &lt;code&gt;/var&lt;/code&gt; folder, the image can be built as follows:&lt;/p&gt;

&lt;p&gt;Assuming &lt;code&gt;Buildroot 2024.11.1&lt;/code&gt; was installed in the &lt;code&gt;/var&lt;/code&gt; directory, the image for the Raspberry Pi 5 can be built with the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;output &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;output
make &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; /var/buildroot-2024.11.1 raspberrypi5_defconfig
make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the build process completes, the resulting image can be written to an SD card using the &lt;code&gt;dd&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;output/images/sdcard.img &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sda &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Double-check the target device (&lt;code&gt;/dev/sda&lt;/code&gt;) before running &lt;code&gt;dd&lt;/code&gt;, as using the wrong device can overwrite critical data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Monitoring the temperature via &lt;code&gt;sysfs&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Once the Raspberry Pi 5 has booted, the system's temperature can be monitored through the &lt;code&gt;sysfs&lt;/code&gt; interface, which exposes thermal sensor data managed by the Kernel's thermal subsystem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntgemj8lssbdc8gh17zh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntgemj8lssbdc8gh17zh.png" alt="CPU temperature" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The device driver responsible for managing the active cooler dynamically adjusts the fan speed based on the system’s temperature. Once the &lt;code&gt;pwm-fan&lt;/code&gt; module is loaded, it automatically regulates the fan according to the thermal zones defined in the device tree.&lt;/p&gt;

&lt;p&gt;The current fan state can be also monitored via the &lt;code&gt;sysfs&lt;/code&gt; interface. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkebfj7j9z1gwo6814t66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkebfj7j9z1gwo6814t66.png" alt="Active cooler being controlled by the device driver" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The value returned corresponds to the current cooling level, which maps to predefined PWM values in the device tree, according to the current CPU temperature (in Celsius):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cooling State&lt;/th&gt;
&lt;th&gt;PWM Duty Cycle&lt;/th&gt;
&lt;th&gt;Current Temperature&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&amp;lt; 50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;50 &amp;lt; current temperature &amp;lt; 60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;125&lt;/td&gt;
&lt;td&gt;60 &amp;lt; current temperature &amp;lt; 67.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;175&lt;/td&gt;
&lt;td&gt;67.5 &amp;lt; current temperature &amp;lt; 75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;&amp;gt; 75&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The active fan can also be controlled from user space by disabling the Kernel module and directly interacting with the PWM &lt;code&gt;sysfs&lt;/code&gt; interface. To begin, export PWM channel 3 by writing its index to &lt;code&gt;/sys/class/pwm/pwmchip2/export&lt;/code&gt;. Once exported, the fan control interface becomes available at &lt;code&gt;/sys/class/pwm/pwmchip2/pwm3/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The image below demonstrates how to enable the device and run the fan at full speed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytjlcfvsyudv3rsdn8jn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytjlcfvsyudv3rsdn8jn.png" alt="Manually controlling the active cooler" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Effective thermal management is essential in embedded Linux systems like the Raspberry Pi 5 to maintain performance and hardware longevity. By enabling the onboard thermal sensor and configuring the active cooler through Device Tree and Kernel options, you can build a responsive and reliable temperature control system.&lt;/p&gt;

&lt;p&gt;Using Buildroot, integrating these features into a custom Linux image becomes a streamlined and repeatable process. Whether you choose to rely on automatic thermal zones or prefer manual control via the &lt;code&gt;sysfs&lt;/code&gt; interface, you have full flexibility to tailor the cooling behavior to your application’s needs.&lt;/p&gt;

&lt;p&gt;For an even more automated solution, check out &lt;a href="https://github.com/paulosell/rpi-hardware-monitor" rel="noopener noreferrer"&gt;this project&lt;/a&gt;, which reads the current temperature and dynamically adjusts the fan speed. If you’d like help integrating it into your Buildroot setup, feel free to reach out. &lt;/p&gt;

</description>
      <category>linux</category>
      <category>embedded</category>
      <category>buildroot</category>
      <category>raspberrypi</category>
    </item>
    <item>
      <title>Enabling Raspberry Pi 5 Onboard Wi-Fi using Buildroot External Tree</title>
      <dc:creator>Paulo Fylippe Sell</dc:creator>
      <pubDate>Sat, 12 Apr 2025 20:36:07 +0000</pubDate>
      <link>https://forem.com/pfs/enabling-raspberry-pi-5-onboard-wi-fi-with-buildroot-1p59</link>
      <guid>https://forem.com/pfs/enabling-raspberry-pi-5-onboard-wi-fi-with-buildroot-1p59</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Buildroot External Tree
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended directory structure
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://buildroot.org/downloads/manual/manual.html#customize" rel="noopener noreferrer"&gt;Buildroot official documentation&lt;/a&gt; recommends the following structure for storing board-specific customizations. When placed outside the main Buildroot source tree, this is referred to as a &lt;em&gt;br2-external tree&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-- board/
|       +-- &amp;lt;boardname&amp;gt;/
|           +-- linux.config
|           +-- busybox.config
|           +-- &amp;lt;other configuration files&amp;gt;
|           +-- post_build.sh
|           +-- post_image.sh
|           +-- rootfs_overlay/
|           |   +-- etc/
|           |   +-- &amp;lt;some files&amp;gt;
|           +-- patches/
|               +-- foo/
|               |   +-- &amp;lt;some patches&amp;gt;
|               +-- libbar/
|                   +-- &amp;lt;some other patches&amp;gt;
|
+-- configs/
|   +-- &amp;lt;boardname&amp;gt;_defconfig
|
+-- package/
|       +-- package1/
|       |    +-- Config.in
|       |    +-- package1.mk
|       +-- package2/
|           +-- Config.in
|           +-- package2.mk
|
+-- Config.in
+-- external.mk
+-- external.desc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A valid &lt;em&gt;br2-external tree&lt;/em&gt; must include at least three essential files, which define the external tree and its customizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;external.desc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;external.mk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Config.in&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;external.desc&lt;/strong&gt; file contains metadata about the &lt;em&gt;br2-external tree&lt;/em&gt; and is required for Buildroot to properly recognize and integrate the external directory. It supports two keywords:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; (mandatory): defines the name of the external tree. Buildroot uses this to create a variable called &lt;code&gt;BR2_EXTERNAL_$(NAME)_PATH&lt;/code&gt;, which holds the absolute path to the external tree. The name must consist of ASCII characters only.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;desc&lt;/code&gt; (optional): provides a short description (recommended a maximum of 40 characters) for the external tree. This description is available within Buildroot as the variable &lt;code&gt;BR2_EXTERNAL_$(NAME)_DESC&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To create a basic &lt;em&gt;br2-external tree&lt;/em&gt; in the home folder and define its &lt;code&gt;external.desc&lt;/code&gt; file, the following can be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/br2-external-tree
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"name: DEV_TO_TREE"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/external.desc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;external.mk&lt;/strong&gt; file includes the Makefiles of all custom packages so that Buildroot knows how to build them. This file can be created by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/external.mk &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
include &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;wildcard &lt;span class="si"&gt;$(&lt;/span&gt;BR2_EXTERNAL_DEV_TO_TREE_PATH&lt;span class="si"&gt;)&lt;/span&gt;/package/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.mk&lt;span class="si"&gt;))&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: BR2_EXTERNAL_DEV_TO_TREE_PATH refers to the name set in &lt;code&gt;external.desc&lt;/code&gt; file earlier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Config.in&lt;/strong&gt; file declares the configuration options for custom packages, allowing them to appear in Buildroot’s &lt;code&gt;menuconfig&lt;/code&gt; interface. A typical &lt;code&gt;Config.in&lt;/code&gt; might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BR2_EXTERNAL_DEV_TO_TREE_PATH&lt;/span&gt;&lt;span class="s2"&gt;/package/package1/Config.in"&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BR2_EXTERNAL_DEV_TO_TREE_PATH&lt;/span&gt;&lt;span class="s2"&gt;/package/package2/Config.in"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now, an empty file will do the job, as we will come back to it later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/br2-external-tree/Config.in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build Configuration for Raspberry Pi 5
&lt;/h2&gt;

&lt;p&gt;With the basis of the &lt;em&gt;br2-external tree&lt;/em&gt; set, the next objective is to configure Builroot building system, using the default configuration for Rasberry Pi 5 board and passing the &lt;em&gt;br2-external tree&lt;/em&gt; path in &lt;code&gt;BR2_EXTERNAL&lt;/code&gt; variable (refer to &lt;a href="https://dev.to/pfs/custom-linux-image-for-raspberry-pi-5-a-guide-with-buildroot-bp3"&gt;this post&lt;/a&gt; to check on how to download and install Buildroot):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/output &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/output
make &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; /var/buildroot-2024.11.1 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;BR2_EXTERNAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/br2-external-tree raspberrypi5_defconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This assumes Buildroot version &lt;code&gt;2024.11.1&lt;/code&gt; is installed in the &lt;code&gt;/var&lt;/code&gt; directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Linux Kernel configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Device Tree
&lt;/h3&gt;

&lt;p&gt;WLAN interface for the Raspberry Pi 5 is defined in two separate &lt;strong&gt;Device Tree Source (DTS)&lt;/strong&gt; files included in the default configuration for Raspberry Pi 5 board in the &lt;a href="https://github.com/raspberrypi/linux/tree/576cc10e1ed50a9eacffc7a05c796051d7343ea4" rel="noopener noreferrer"&gt;Linux Kernel source&lt;/a&gt;. These files are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts" rel="noopener noreferrer"&gt;&lt;code&gt;arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm/boot/dts/broadcom/bcm2712.dtsi" rel="noopener noreferrer"&gt;&lt;code&gt;arch/arm/boot/dts/broadcom/bcm2712.dtsi&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're unfamiliar with DTS files, one of my &lt;a href="https://dev.to/pfs/enabling-ethernet-support-and-openssh-on-raspberry-pi-5-with-buildroot-57dk"&gt;previous posts&lt;/a&gt; provides a brief introduction.&lt;/p&gt;

&lt;p&gt;The SDIO interface used by the onboard Wi-Fi is described in the following DTS entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sdio2: mmc@1100000 {
    compatible = "brcm,bcm2712-sdhci";
    reg = &amp;lt;0x10 0x01100000  0x0 0x260&amp;gt;,
          &amp;lt;0x10 0x01100400  0x0 0x200&amp;gt;;
    reg-names = "host", "cfg";
    interrupts = &amp;lt;GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH&amp;gt;;
    clocks = &amp;lt;&amp;amp;clk_emmc2&amp;gt;;
    sdhci-caps-mask = &amp;lt;0x0000C000 0x0&amp;gt;;
    sdhci-caps = &amp;lt;0x0 0x0&amp;gt;;
    supports-cqe;
    mmc-ddr-3_3v;
    status = "disabled";
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interface is later referenced and enabled in another section of the DTS, which also includes the WLAN device node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;amp;sdio2 {
    pinctrl-0 = &amp;lt;&amp;amp;sdio2_30_pins&amp;gt;;
    pinctrl-names = "default";
    bus-width = &amp;lt;4&amp;gt;;
    vmmc-supply = &amp;lt;&amp;amp;wl_on_reg&amp;gt;;
    sd-uhs-ddr50;
    non-removable;
    status = "okay";
    #address-cells = &amp;lt;1&amp;gt;;
    #size-cells = &amp;lt;0&amp;gt;;

    wifi: wifi@1 {
        reg = &amp;lt;1&amp;gt;;
        compatible = "brcm,bcm4329-fmac";
        local-mac-address = [00 00 00 00 00 00];
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Device drivers
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The following options should be enabled in the Kernel configuration by running &lt;code&gt;make linux-menuconfig&lt;/code&gt; inside &lt;code&gt;output&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[*] Networking support ---&amp;gt;
  [*] Wireless ---&amp;gt;
    &amp;lt;M&amp;gt; cfg80211 - wireless configuration API
    [*] enable powersave by default
    [*] support CRDA
    [*] cfg80211 wireless extensions compatibility

Device Drivers ---&amp;gt;
  [*] Network device support ---&amp;gt;
    [*] Wireless LAN ---&amp;gt; 
       [*] Broadcom devices
       &amp;lt;M&amp;gt; Broadcom FullMAC WLAN driver
       [*] SDIO bus interface support for FullMAC driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;All other Kernel options were left at their default values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Firmware Custom Package
&lt;/h2&gt;

&lt;p&gt;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, &lt;em&gt;br2-external tree&lt;/em&gt; feature can be leveraged to create a custom package that fetches the firmware from its &lt;a href="https://web.git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git" rel="noopener noreferrer"&gt;official repository&lt;/a&gt; and installs it in the appropriate location within the target root filesystem&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Custom Package
&lt;/h3&gt;

&lt;p&gt;First, create a folder to hold the files that describe your custom package (i.e. &lt;code&gt;.mk&lt;/code&gt; and &lt;code&gt;Config.in&lt;/code&gt;files):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/br2-external-tree/package/brcmfmac-firmware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the Config.in file to define how this package appears in Buildroot's &lt;code&gt;menuconfig&lt;/code&gt; and what option name it uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/package/brcmfmac-firmware/Config.in &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' 
config BR2_PACKAGE_BRCMFMAC_FIRMWARE
  bool "BRCMFMAC Firmware"
  default n
  help
    Downloads and install CYW43455 firmware from Linux Kernel source
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, define the &lt;code&gt;.mk&lt;/code&gt; file to tell Buildroot where to fetch the firmware and how to install it under &lt;code&gt;/lib/firmware/brcm&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/package/brcmfmac-firmware/brcmfmac-firmware.mk &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' 
BRCMFMAC_FIRMWARE_VERSION := 20250311
BRCMFMAC_FIRMWARE_SOURCE := linux-firmware-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;BRCMFMAC_FIRMWARE_VERSION&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;.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
  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;INSTALL&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt; -D -m 0644 &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;@D&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/cypress/cyfmac43455-sdio.bin &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;TARGET_DIR&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/lib/firmware/brcm/brcmfmac43455-sdio.bin

  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;INSTALL&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt; -D -m 0644 &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;@D&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/cypress/cyfmac43455-sdio.clm_blob &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;TARGET_DIR&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob

  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;INSTALL&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt; -D -m 0644 &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;@D&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/brcm/brcmfmac43455-sdio.raspberrypi,4-model-b.txt &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;TARGET_DIR&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/lib/firmware/brcm/brcmfmac43455-sdio.txt

  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;INSTALL&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt; -D -m 0644 &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;@D&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/cypress/cyfmac43455-sdio.bin &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;TARGET_DIR&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.bin

  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;INSTALL&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt; -D -m 0644 &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;@D&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/cypress/cyfmac43455-sdio.clm_blob &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;TARGET_DIR&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.clm_blob

  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;INSTALL&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt; -D -m 0644 &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;@D&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/brcm/brcmfmac43455-sdio.raspberrypi,4-model-b.txt &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;TARGET_DIR&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.txt
endef

&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;generic-package&lt;span class="si"&gt;))&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Registering the Package
&lt;/h3&gt;

&lt;p&gt;Finally, add an entry in the top-level &lt;code&gt;Config.in&lt;/code&gt; file of your &lt;code&gt;br2-external tree&lt;/code&gt; so the package appears in the &lt;code&gt;menuconfig&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/Config.in &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' 
menu "Raspberry Pi 5 Customizations"
source "&lt;/span&gt;&lt;span class="nv"&gt;$BR2_EXTERNAL_DEV_TO_TREE_PATH&lt;/span&gt;&lt;span class="sh"&gt;/package/brcmfmac-firmware/Config.in"
endmenu
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And enable the option just that had just been created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/output
make menuconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new option should be located in &lt;code&gt;External options -&amp;gt; Raspberry Pi 5 Customizations&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  WPA Supplicant and Wireless Interface Setup
&lt;/h2&gt;

&lt;p&gt;Jumping into the user space, &lt;strong&gt;WPA Supplicant&lt;/strong&gt; can be used to manage the wireless interface. This package in located under &lt;code&gt;Target packages -&amp;gt; Networking applications&lt;/code&gt; after running &lt;code&gt;make menuconfig&lt;/code&gt; from &lt;code&gt;output folder&lt;/code&gt;. The following options should be enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BR2_PACKAGE_WPA_SUPPLICANT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;span class="nv"&gt;BR2_PACKAGE_WPA_SUPPLICANT_WEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;span class="nv"&gt;BR2_PACKAGE_WPA_SUPPLICANT_CLI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;span class="nv"&gt;BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, enable the &lt;code&gt;iw&lt;/code&gt; and &lt;code&gt;wireless-regdb&lt;/code&gt; packages from the same section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BR2_PACKAGE_IW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;span class="nv"&gt;BR2_PACKAGE_WIRELESS_REGDB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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, &lt;em&gt;br2-external tree&lt;/em&gt; will be used to store this configuration under the &lt;code&gt;rootfs_overlay&lt;/code&gt; folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/network/interfaces &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
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
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/wpa_supplicant.conf &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=BR

network={
ssid=&amp;lt;your_ssid&amp;gt;
psk=&amp;lt;your_passphrase&amp;gt;
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;❗ Make sure to edit this file passing the SSID and the password for the desired network.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Post-Boot Driver Initialization
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;/lib/firmware/brcm&lt;/code&gt;. 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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/init.d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/init.d/S35wlan_modules &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
#!/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 "&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="sh"&gt;" in
  start)
    printf "Installing wlan modules... "
    install_wlan_modules
    [ &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="sh"&gt; -eq 0 ] &amp;amp;&amp;amp; echo "OK" || echo "FAIL"
    ;;
  stop)
    printf "Uninstalling wlan modules... "
    uninstall_wlan_modules
    [ &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="sh"&gt; -eq 0 ] &amp;amp;&amp;amp; echo "OK" || echo "FAIL"
    ;;
  restart)
    printf "Uninstalling wlan modules... "
    uninstall_wlan_modules
    [ &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="sh"&gt; -eq 0 ] &amp;amp;&amp;amp; echo "OK" || echo "FAIL"

    printf "Installing wlan modules... "
    install_wlan_modules
    [ &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="sh"&gt; -eq 0 ] &amp;amp;&amp;amp; echo "OK" || echo "FAIL"
    ;;
  *)
    echo "Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="sh"&gt; {start|stop|restart}"
    exit 1
    ;;
esac

exit &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to add execution permission for the script we just created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/br2-external-tree/board/raspberrypi5/rootfs_overlay/etc/init.d/S35wlan_modules 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring the Root Filesystem Overlay
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BR2_ROOTFS_OVERLAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;BR2_EXTERNAL_DEV_TO_TREE_PATH&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/board/raspberrypi5/rootfs_overlay"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once everything is saved, the compilation can be triggered by running &lt;code&gt;make&lt;/code&gt; inside &lt;code&gt;output&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flashing the Image to an SD Card
&lt;/h2&gt;

&lt;p&gt;After the compilation is complete without errors, the final binary file will be located in the &lt;code&gt;output/images&lt;/code&gt; folder and will be named &lt;code&gt;sdcard.img&lt;/code&gt;. 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):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dd if=images/sdcard.img of=/dev/sda status=progress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;📡 And that’s it! You’ve just enabled the Raspberry Pi 5's onboard Wi-Fi from scratch using Buildroot. From configuring kernel modules and creating a custom firmware package to using &lt;code&gt;wpa_supplicant&lt;/code&gt; and automating initialization on boot, you now have control over the wireless interface for custom networking scenarios.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw81op1vcsfohcwe5m4rr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw81op1vcsfohcwe5m4rr.png" alt="Sucessfull wi-fi connection" width="800" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you found this post helpful or ran into issues along the way, feel free to drop your questions, suggestions, or just share your thoughts in the comments section. I’d love to hear how you're using Raspberry Pi 5 in your own projects — or if there's something you’d like to see covered in a future post!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>buildroot</category>
      <category>raspberrypi</category>
      <category>embedded</category>
    </item>
    <item>
      <title>Enabling Ethernet support and OpenSSH on Raspberry Pi 5 with Buildroot</title>
      <dc:creator>Paulo Fylippe Sell</dc:creator>
      <pubDate>Mon, 07 Apr 2025 11:15:17 +0000</pubDate>
      <link>https://forem.com/pfs/enabling-ethernet-support-and-openssh-on-raspberry-pi-5-with-buildroot-57dk</link>
      <guid>https://forem.com/pfs/enabling-ethernet-support-and-openssh-on-raspberry-pi-5-with-buildroot-57dk</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/pfs/custom-linux-image-for-raspberry-pi-5-a-guide-with-buildroot-bp3"&gt;last post&lt;/a&gt;, I discussed logging into a Raspberry Pi 5 image built with Buildroot over a serial connection. However, this method requires either the official &lt;a href="https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html" rel="noopener noreferrer"&gt;debug probe&lt;/a&gt; or a more common &lt;a href="https://www.mouser.com/ProductDetail/Adafruit/954?qs=GURawfaeGuBg0XxCeRWeUA%3D%3D" rel="noopener noreferrer"&gt;serial adapter&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Another widely used alternative is leveraging the Raspberry Pi 5's Ethernet port to log into the system using SSH.&lt;/p&gt;

&lt;h2&gt;
  
  
  Device Tree configuration
&lt;/h2&gt;

&lt;p&gt;The Ethernet interface for the Raspberry Pi 5 is defined in two different &lt;strong&gt;Device Tree Source (DTS)&lt;/strong&gt; files included in the &lt;a href="https://github.com/raspberrypi/linux/tree/576cc10e1ed50a9eacffc7a05c796051d7343ea4" rel="noopener noreferrer"&gt;Linux Kernel source&lt;/a&gt;. These files are:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts" rel="noopener noreferrer"&gt;&lt;code&gt;arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm/boot/dts/broadcom/rp1.dtsi" rel="noopener noreferrer"&gt;&lt;code&gt;arch/arm/boot/dts/broadcom/rp1.dtsi&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A &lt;strong&gt;DTS (Device Tree Source)&lt;/strong&gt; file is a human-readable text file that describes hardware components and their configurations for systems using the &lt;strong&gt;Device Tree&lt;/strong&gt;, such as Linux-based embedded systems. This file is compiled into a &lt;strong&gt;DTB (Device Tree Blob)&lt;/strong&gt;, which the operating system reads at boot time to understand the hardware layout without relying on hardcoded Kernel configurations.  &lt;/p&gt;

&lt;p&gt;The Ethernet interface is described in the following DTS entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rp1_eth: ethernet@100000 {
    reg = &amp;lt;0xc0 0x40100000  0x0 0x4000&amp;gt;;
    compatible = "cdns,macb";
    #address-cells = &amp;lt;1&amp;gt;;
    #size-cells = &amp;lt;0&amp;gt;;
    interrupts = &amp;lt;RP1_INT_ETH IRQ_TYPE_LEVEL_HIGH&amp;gt;;
    clocks = &amp;lt;&amp;amp;macb_pclk &amp;amp;macb_hclk &amp;amp;rp1_clocks RP1_CLK_ETH_TSU&amp;gt;;
    clock-names = "pclk", "hclk", "tsu_clk";
    phy-mode = "rgmii-id";
    cdns,aw2w-max-pipe = /bits/ 8 &amp;lt;8&amp;gt;;
    cdns,ar2r-max-pipe = /bits/ 8 &amp;lt;8&amp;gt;;
    cdns,use-aw2b-fill;
    local-mac-address = [00 00 00 00 00 00];
    status = "disabled";
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it is referenced and enabled in the following DTS entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;amp;rp1_eth {
    status = "okay";
    phy-handle = &amp;lt;&amp;amp;phy1&amp;gt;;
    phy-reset-gpios = &amp;lt;&amp;amp;rp1_gpio 32 GPIO_ACTIVE_LOW&amp;gt;;
    phy-reset-duration = &amp;lt;5&amp;gt;;

    phy1: ethernet-phy@1 {
        reg = &amp;lt;0x1&amp;gt;;
        brcm,powerdown-enable;
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing and Setting Up Buildroot
&lt;/h2&gt;

&lt;p&gt;Assuming all required dependencies are already installed, Buildroot can be downloaded and extracted as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/buildroot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/buildroot
wget https://buildroot.org/downloads/buildroot-2024.11.1.tar.gz 
&lt;span class="nb"&gt;tar &lt;/span&gt;zxf buildroot-2024.11.1.tar.gz &lt;span class="nt"&gt;--strip-components&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create an output directory where Buildroot will store all build artifacts, and configure it for the Raspberry Pi 5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/buildroot 
&lt;span class="nb"&gt;mkdir &lt;/span&gt;output &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;output
make &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; ../buildroot-2025.02 raspberrypi5_defconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enabling Ethernet Support for Raspberry Pi 5
&lt;/h2&gt;

&lt;p&gt;Raspberry Pi 5 features a &lt;strong&gt;Cadence Ethernet controller&lt;/strong&gt; integrated into the RP1 chip and a &lt;strong&gt;Broadcom BCM54213 PHY&lt;/strong&gt; connected to it. To support Ethernet networking, the following Kernel configuration options must be enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;CONFIG_NET_VENDOR_CADENCE
CONFIG_MACB
CONFIG_BROADCOM_PHY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These configuration can be enable from within Buildroot &lt;code&gt;output&lt;/code&gt;  folder, by simply running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make linux-menuconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These options ensure that the necessary device drivers are compiled to support Ethernet functionality. The rest of the Kernel configuration, including network stack configuration, remains as per the &lt;a href="https://github.com/raspberrypi/linux/blob/576cc10e1ed50a9eacffc7a05c796051d7343ea4/arch/arm64/configs/bcm2712_defconfig" rel="noopener noreferrer"&gt;default&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling OpenSSH in Buildroot
&lt;/h2&gt;

&lt;p&gt;To enable the OpenSSH server and client in your image, open the Buildroot menu configuration tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make menuconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, navigate to &lt;code&gt;Target packages -&amp;gt; Networking applications&lt;/code&gt;. Once inside, scroll down to find and enable OpenSSH:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faabvzj5j8st26f4ow18r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faabvzj5j8st26f4ow18r.png" alt="OpenSSH enable" width="685" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also will need &lt;code&gt;ifupdown&lt;/code&gt; scripts enabled to be able to bring our network up when needed. While still in &lt;code&gt;Target packages -&amp;gt; Networking applications&lt;/code&gt;, make sure the following option is enable (should be default for Raspberry Pi 5):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BR2_PACKAGE_IFUPDOWN_SCRIPTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Customizing the Root Filesystem
&lt;/h2&gt;

&lt;p&gt;In order to store OpenSSH custom configuration file, we can take advantage of a Buildroot feature called &lt;a href="https://buildroot.org/downloads/manual/manual.html#customize" rel="noopener noreferrer"&gt;RootFS Overlay&lt;/a&gt;. We will also use this feature to configure our network interface.&lt;/p&gt;

&lt;p&gt;Before enabling the feature, it is necessary to create a folder that will store the RootFS overlay. The folder must have the following tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-- rootfs_overlay
|    +-- etc/
|        +-- ssh/
|            +-- sshd_config
|        +-- network/
|            +-- interfaces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create such a folder-tree, one can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/rootfs_overlay/etc/ssh ~/rootfs_overlay/etc/network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sshd_config&lt;/code&gt; must contain the configuration for the ssh server we are building. In this case, we could only enable root login over ssh, by running the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"PermitRootLogin yes"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/rootfs_overlay/etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that enabling root login over ssh is not recommended in a real-life application due to cyber security reasons.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the network configuration, &lt;code&gt;interfaces&lt;/code&gt; file should be filled using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/rootfs_overlay/etc/network/interfaces &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address 192.168.0.199
  netmask 255.255.255.0
  gateway 192.168.0.1
  pre-up /etc/network/nfs_check
  wait-delay 15
  hostname &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back on &lt;code&gt;output&lt;/code&gt; folder, on Buildroot menu one must enable the following option, passing the path of the &lt;code&gt;rootfs_overlay&lt;/code&gt; folder that had just been created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BR2_ROOTFS_OVERLAY="~/rootfs_overlay"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By setting this option, Buildroot will copy each file or folder from the configured path directly over the target file system after it has been built. Hidden directories of version control systems, like .git, .svn, .hg, etc., files called .empty and files ending in ~ are excluded from the copy. &lt;/p&gt;

&lt;p&gt;We should also set the &lt;code&gt;root&lt;/code&gt; password so we can later login over ssh. Using the arrow keys and Enter key to navigate through the Buildroot menu, the root password can be set by on the following option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-&amp;gt; System configuration
| -&amp;gt; Enable root login with password (BR2_TARGET_ENABLE_ROOT_LOGIN [=y]) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once everything is set up, the compilation can be triggered by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the compilation is finished without errors, all is left to do is to write the image into the SD card (assuming it is enumerated as /dev/sda), by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dd if=images/sdcard.img of=/dev/sda status=progress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connecting to the Board Over SSH
&lt;/h2&gt;

&lt;p&gt;After finishing flashing and powering up the board, it is necessary to connect an Ethernet cable between the board and the host computer. It is also necessary to set a static IP on the host's network interface so we can communicate with the board:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ifconfig interface_name down
ifconfig interface_name 192.168.0.190 netmask 255.255.255.0
ifconfig interface_name up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we must install OpenSSH client on our host computer, and run the &lt;code&gt;ssh&lt;/code&gt; command to login into &lt;code&gt;root&lt;/code&gt; user using the IP address we configured previously on &lt;code&gt;interfaces&lt;/code&gt; file (assuming Debian/Ubuntu environment):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;openssh-client
ssh root@192.168.0.199
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything went fine, you should now be logged in the board and be able to use it over SSH protocol. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4h9aqmwovgmo6dlrjw0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4h9aqmwovgmo6dlrjw0.png" alt="Successful SSH login " width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that’s it for this post! With everything set up, your Raspberry Pi 5 Buildroot image is ready to roll over SSH. Whether you're building a cool project or just diving deeper into embedded Linux, I hope this guide helped you somehow.  &lt;/p&gt;

&lt;p&gt;💬 If you found this helpful, drop a like or leave a comment — I'd love to hear what you're working on!&lt;/p&gt;

</description>
      <category>buildroot</category>
      <category>raspberrypi</category>
      <category>linux</category>
      <category>embedded</category>
    </item>
    <item>
      <title>Custom Linux Image for Raspberry Pi 5: A Guide with Buildroot</title>
      <dc:creator>Paulo Fylippe Sell</dc:creator>
      <pubDate>Tue, 01 Apr 2025 20:49:27 +0000</pubDate>
      <link>https://forem.com/pfs/custom-linux-image-for-raspberry-pi-5-a-guide-with-buildroot-bp3</link>
      <guid>https://forem.com/pfs/custom-linux-image-for-raspberry-pi-5-a-guide-with-buildroot-bp3</guid>
      <description>&lt;p&gt;Earlier this year, I got my hands on a Raspberry Pi 5 with the goal of expanding my knowledge of embedded systems, device drivers, the Linux Kernel, and related technologies. My objective is to explore several features of the Raspberry Pi 5, systematically enabling and configuring its functionalities until I achieve a fully functional image capable of managing all the board's main peripherals.  Since I was already working on a project that uses Buildroot to generate a Linux system from scratch, I decided to integrate it into my learning process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Buildroot?
&lt;/h2&gt;

&lt;p&gt;According to its own documentation, Buildroot is a powerful tool that simplifies and automates the process of creating embedded Linux images, including the bootloader, Linux kernel, and root filesystem. It also generates a cross-compilation toolchain that can be used independently of Buildroot. Supporting a wide range of processors, Buildroot allows users to customize a Linux image from scratch according to the own needs. Fortunately, it includes several default configurations for various boards — including the Raspberry Pi 5 — making the setup process much more accessible.&lt;/p&gt;

&lt;p&gt;By the time I started working on this project, the default configuration for Raspberry Pi 5 was already available in Buildroot 2024.11.1, which is the version I chose to use. Before diving into building the Linux image, the host computer must meet several mandatory and optional requirements. To install all the necessary packages in a Debian/Ubuntu environment (sudo may be required), you can run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get upgrade &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; which &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;sed &lt;/span&gt;binutils build-essential diffutils gcc g++ bash patch &lt;span class="nb"&gt;gzip&lt;/span&gt;   &lt;span class="se"&gt;\&lt;/span&gt;
bzip2 perl &lt;span class="nb"&gt;tar &lt;/span&gt;cpio unzip rsync file bc findutils wget python3   &lt;span class="se"&gt;\&lt;/span&gt;
libncurses5-dev libncursesw5-dev libncurses5 libncursesw5 git    &lt;span class="se"&gt;\&lt;/span&gt;
curl cvs mercurial openssh-client subversion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once all the packages are installed, we’re ready to start building our image. To download Buildroot 2024.11.1, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/buildroot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/buildroot
wget https://buildroot.org/downloads/buildroot-2024.11.1.tar.gz 
&lt;span class="nb"&gt;tar &lt;/span&gt;zxf buildroot-2024.11.1.tar.gz &lt;span class="nt"&gt;--strip-components&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands above will download and extract the specified Buildroot version. If you need a different version, you can find all available releases &lt;a href="https://buildroot.org/downloads/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Buildroot follows a quarterly release cycle, with monthly bug-fix updates to ensure stability and improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the build
&lt;/h2&gt;

&lt;p&gt;After downloading Buildroot, the next step is to configure our build using the default Raspberry Pi 5 configuration. It's best practice to build the image outside the Buildroot source folder. To do this, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/buildroot 
&lt;span class="nb"&gt;mkdir &lt;/span&gt;output &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;output
make &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; ../buildroot-2025.02 raspberrypi5_defconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see an output similar to the image below, the configuration was successful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9089q1gxxz5addxb7pys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9089q1gxxz5addxb7pys.png" alt="Expected output after configuring the build" width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before starting the build, we can make some customization, such as setting a root password for the system. To do this, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make menuconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open a curses-based configurator, similar to the one used in the Linux kernel project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favk238mv1szhkb2fx81u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favk238mv1szhkb2fx81u.png" alt="Output of make menuconfig" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the arrow keys and Enter key to navigate through the menu, you can set the root password by going to the following option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-&amp;gt; System configuration
| -&amp;gt; Enable root login with password (BR2_TARGET_ENABLE_ROOT_LOGIN [=y]) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After saving your changes and exiting the configuration menu, you can start the build process by simply running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will trigger the compilation of the root filesystem and the Linux kernel for the Raspberry Pi 5. The process can take one to two hours, as it involves building everything from scratch, including host dependencies and the toolchain.&lt;/p&gt;

&lt;p&gt;After the compilation is complete without errors, the final binary file will be located in the &lt;code&gt;images&lt;/code&gt; folder and will be named &lt;code&gt;sdcard.img&lt;/code&gt;. This is the file that needs to be written to the SD card to boot the Raspberry Pi board. To write the image to the SD card (assuming it is enumerated as /dev/sda), run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dd if=images/sdcard.img of=/dev/sda status=progress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the SD card has finished flashing, the final step is to power up the board. You should be able to log in to the system using the password you set earlier. A &lt;a href="https://www.raspberrypi.com/products/debug-probe/" rel="noopener noreferrer"&gt;serial connection&lt;/a&gt; can be used to access the system and log in. The serial session will also be helpful to troubleshoot any issue you face while booting the system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frngf7ss640ehvfzjcq8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frngf7ss640ehvfzjcq8j.png" alt="Successful login" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;🔥 And that's it! You’ve successfully built a custom Linux image for your Raspberry Pi 5 using Buildroot, configured it, and flashed it onto an SD card. This process not only gives you a deeper understanding of embedded systems, but also provides you with a powerful, customizable environment tailored to your needs.&lt;/p&gt;

&lt;p&gt;If you have any questions or run into issues, feel free to leave a comment below! I'm happy to help with any doubts you may have. Additionally, if you've made any interesting customizations or run into unique challenges, I’d love to hear about them in the comments. Let’s keep the discussion going!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For more detailed information and advanced configurations, you can explore the &lt;a href="https://buildroot.org/downloads/manual/manual.html" rel="noopener noreferrer"&gt;official Buildroot manual&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>buildroot</category>
      <category>raspberrypi</category>
      <category>linux</category>
      <category>embedded</category>
    </item>
  </channel>
</rss>
