<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bill Van Leeuwen's blog]]></title><description><![CDATA[Bill Van Leeuwen's blog]]></description><link>https://blog.billvanleeuwen.ca</link><generator>RSS for Node</generator><lastBuildDate>Thu, 14 May 2026 07:20:17 GMT</lastBuildDate><atom:link href="https://blog.billvanleeuwen.ca/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Writing a Linux IIO Driver for the MS8607 Sensor]]></title><description><![CDATA[This post covers the development of a Linux kernel driver for the MS8607 pressure, humidity, and temperature sensor on the BeagleBone Black. The driver integrates with the IIO (Industrial I/O) subsystem to provide a standard interface for userspace a...]]></description><link>https://blog.billvanleeuwen.ca/writing-a-linux-iio-driver-for-the-ms8607-sensor</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/writing-a-linux-iio-driver-for-the-ms8607-sensor</guid><category><![CDATA[embedded linux]]></category><category><![CDATA[beaglebone black]]></category><category><![CDATA[linux device drivers]]></category><category><![CDATA[device-driver]]></category><category><![CDATA[embedded]]></category><category><![CDATA[C]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Sun, 16 Nov 2025 22:50:14 GMT</pubDate><content:encoded><![CDATA[<p>This post covers the development of a Linux kernel driver for the MS8607 pressure, humidity, and temperature sensor on the BeagleBone Black. The driver integrates with the IIO (Industrial I/O) subsystem to provide a standard interface for userspace applications.</p>
<p><strong>Repository</strong>: https://github.com/billvanleeuwen424/ms8607-driver</p>
<h2 id="heading-background">Background</h2>
<p>Device drivers bridge hardware and the operating system. Without a driver, the kernel can't communicate with hardware devices. For the MS8607, the driver needs to:</p>
<ul>
<li><p>Communicate over I2C with two sensor addresses (0x76 for pressure/temp, 0x40 for humidity)</p>
</li>
<li><p>Read factory calibration data from PROM and validate with CRC</p>
</li>
<li><p>Convert raw ADC values to pressure (mbar), temperature (°C), and humidity (%RH)</p>
</li>
<li><p>Expose data through IIO's sysfs interface at <code>/sys/bus/iio/devices/</code></p>
</li>
</ul>
<h2 id="heading-hardware-setup">Hardware Setup</h2>
<p>I utilized this pinout diagram from element14 <a target="_blank" href="https://community.element14.com/products/devtools/single-board-computers/next-genbeaglebone/b/blog/posts/controlling-the-beaglebone-black-s-gpio-pins-from-the-web-using-drupal"><strong>here</strong></a><a target="_blank" href="https://community.element14.com/products/devtools/single-board-computers/next-genbeaglebone/b/blog/posts/controlling-the-beaglebone-black-s-gpio-pins-from-the-web-using-drupal">.</a></p>
<p>The MS8607 is mounted on an Adafruit breakout board and connected to the BeagleBone Black I2C2 bus:</p>
<pre><code class="lang-bash">P9_19 (I2C2_SCL) → SCL
P9_20 (I2C2_SDA) → SDA
P9_3  (3.3V)     → VIN
P9_1  (GND)      → GND
</code></pre>
<p>I had the board connected up like so on this very professional breadboard:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763332962338/f06c757a-fb0e-4e1f-be4f-52d358f09254.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-validating-i2c-communication">Validating I2C Communication</h3>
<p>Standard practice is to run <code>i2cdetect</code> first:</p>
<pre><code class="lang-bash">sudo i2cdetect -y 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
</code></pre>
<p>Nothing showed up. The MS8607 doesn't respond to <code>i2cdetect</code> probing—it requires specific command sequences. Manual validation with <code>i2cget</code> and <code>i2cset</code> confirmed both sensors were functional</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Test humidity sensor at 0x40</span>
i2cget -y 2 0x40 0xE7
<span class="hljs-comment"># Output: 0x02</span>

<span class="hljs-comment"># Test pressure/temp sensor at 0x76</span>
i2cset -y 2 0x76 0x5A
i2ctransfer -y 2 w1@0x76 0x00 r3
<span class="hljs-comment"># Output: 0x85 0x4f 0x37</span>
</code></pre>
<h2 id="heading-device-tree-configuration">Device Tree Configuration</h2>
<p>I had to learn a lot about device trees for this project. Again, I recommend Bootlin documentation extremely useful! I utilized this slide deck on <a target="_blank" href="https://bootlin.com/pub/conferences/2021/webinar/petazzoni-device-tree-101/petazzoni-device-tree-101.pdf">Device Tree 101 from Bootlin.</a></p>
<p>The MS8607 contains two sensors on one chip with different I2C addresses. This presented an architecture choice: write two separate drivers (one per sensor) or a single driver managing both.</p>
<h3 id="heading-initial-approach">Initial Approach</h3>
<p>The first device tree had two nodes, both enabled:</p>
<pre><code class="lang-bash">ms8607-pt@76 {
    compatible = <span class="hljs-string">"te,ms8607-pt"</span>;
    reg = &lt;0x76&gt;;
    status = <span class="hljs-string">"okay"</span>;
};

ms8607-h@40 {
    compatible = <span class="hljs-string">"te,ms8607-h"</span>;
    reg = &lt;0x40&gt;;
    status = <span class="hljs-string">"okay"</span>;
};
</code></pre>
<h3 id="heading-the-problem">The Problem</h3>
<p>With both nodes at <code>status = "okay"</code>, the kernel instantiates I2C devices at both addresses during boot. When the driver tried to create a dummy client for 0x40 using <code>devm_i2c_new_dummy_device()</code>, it failed with <code>-EBUSY</code> (error -16)—the address was already taken.</p>
<h3 id="heading-solution">Solution</h3>
<p>Only the primary sensor at 0x76 has <code>status = "okay"</code>. The secondary sensor is documented but disabled:</p>
<pre><code class="lang-bash">/* Primary - driver binds here */
ms8607@76 {
    compatible = <span class="hljs-string">"te,ms8607"</span>;
    reg = &lt;0x76&gt;;
    status = <span class="hljs-string">"okay"</span>;
};

/* Secondary - documented but disabled */
ms8607-h@40 {
    compatible = <span class="hljs-string">"te,ms8607-humidity"</span>;
    reg = &lt;0x40&gt;;
    status = <span class="hljs-string">"disabled"</span>;
};
</code></pre>
<p>The driver creates the humidity sensor client internally. This exposes all three channels (pressure, temperature, humidity) through a single IIO device.</p>
<h2 id="heading-driver-implementation">Driver Implementation</h2>
<h3 id="heading-development-tools">Development Tools</h3>
<p>I used Claude Code for parts of this project—parsing datasheet formulas, generating the CI/CD pipeline, and discussing architecture trade-offs. It was useful for accelerating tasks that would normally require reading documentation or trial-and-error. Hardware debugging and sensor validation still required hands-on work with the BeagleBone.</p>
<h3 id="heading-calibration-and-crc-validation">Calibration and CRC Validation</h3>
<p>The pressure/temperature sensor stores factory calibration coefficients (C1-C6) in PROM. These coefficients are used in the datasheet's formulas to convert raw ADC values into calibrated pressure and temperature readings. If the coefficients are corrupted, all sensor readings will be wrong.</p>
<p>The driver reads the PROM once during probe and validates the data with a 4-bit CRC:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">ms8607_load_calibration</span><span class="hljs-params">(struct ms8607_data *data)</span>
</span>{
    <span class="hljs-keyword">int</span> ret;
    u16 prom[<span class="hljs-number">8</span>];

    ret = ms8607_read_prom_words(data-&gt;client, prom);
    <span class="hljs-keyword">if</span> (ret)
        <span class="hljs-keyword">return</span> ret;

    <span class="hljs-keyword">if</span> (!ms8607_validate_prom_crc(prom)) {
        dev_err(&amp;data-&gt;client-&gt;dev, <span class="hljs-string">"PROM CRC validation failed\n"</span>);
        <span class="hljs-keyword">return</span> -EIO;
    }

    <span class="hljs-built_in">memcpy</span>(data-&gt;calibration, prom, <span class="hljs-keyword">sizeof</span>(data-&gt;calibration));
    data-&gt;calibration_valid = <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<h3 id="heading-sensor-readings">Sensor Readings</h3>
<p>Each sensor requires triggering an ADC conversion, waiting for completion, then reading the result.</p>
<p><strong>Humidity</strong> (16-bit):</p>
<pre><code class="lang-c"><span class="hljs-comment">// Trigger no-hold measurement</span>
i2c_smbus_write_byte(client_h, <span class="hljs-number">0xF5</span>);
msleep(<span class="hljs-number">9</span>);  <span class="hljs-comment">// ADC conversion time</span>

<span class="hljs-comment">// Read result</span>
adc = i2c_smbus_read_word_data(client_h, <span class="hljs-number">0xE5</span>);

<span class="hljs-comment">// Convert to 0.01%RH units</span>
humidity = <span class="hljs-number">-600</span> + ((<span class="hljs-number">12500</span> * adc) &gt;&gt; <span class="hljs-number">16</span>);
</code></pre>
<p><strong>Pressure</strong> (24-bit, requires temperature compensation):</p>
<pre><code class="lang-c"><span class="hljs-comment">// Trigger temperature conversion</span>
i2c_smbus_write_byte(client, <span class="hljs-number">0x58</span>);
msleep(<span class="hljs-number">9</span>);

<span class="hljs-comment">// Read D2 (raw temperature)</span>
i2c_smbus_write_byte(client, <span class="hljs-number">0x00</span>);
i2c_smbus_read_i2c_block_data(client, <span class="hljs-number">0x00</span>, <span class="hljs-number">3</span>, buf);
D2 = (buf[<span class="hljs-number">0</span>] &lt;&lt; <span class="hljs-number">16</span>) | (buf[<span class="hljs-number">1</span>] &lt;&lt; <span class="hljs-number">8</span>) | buf[<span class="hljs-number">2</span>];

<span class="hljs-comment">// Trigger pressure conversion</span>
i2c_smbus_write_byte(client, <span class="hljs-number">0x48</span>);
msleep(<span class="hljs-number">9</span>);

<span class="hljs-comment">// Read D1 (raw pressure)</span>
i2c_smbus_write_byte(client, <span class="hljs-number">0x00</span>);
i2c_smbus_read_i2c_block_data(client, <span class="hljs-number">0x00</span>, <span class="hljs-number">3</span>, buf);
D1 = (buf[<span class="hljs-number">0</span>] &lt;&lt; <span class="hljs-number">16</span>) | (buf[<span class="hljs-number">1</span>] &lt;&lt; <span class="hljs-number">8</span>) | buf[<span class="hljs-number">2</span>];

<span class="hljs-comment">// Apply calibration (datasheet formulas)</span>
dT = D2 - (C5 &lt;&lt; <span class="hljs-number">8</span>);
TEMP = <span class="hljs-number">2000</span> + ((dT * C6) &gt;&gt; <span class="hljs-number">23</span>);
OFF = (C2 &lt;&lt; <span class="hljs-number">17</span>) + ((C4 * dT) &gt;&gt; <span class="hljs-number">6</span>);
SENS = (C1 &lt;&lt; <span class="hljs-number">16</span>) + ((C3 * dT) &gt;&gt; <span class="hljs-number">7</span>);
P = (((D1 * SENS) &gt;&gt; <span class="hljs-number">21</span>) - OFF) &gt;&gt; <span class="hljs-number">15</span>;
</code></pre>
<h3 id="heading-iio-integration">IIO Integration</h3>
<p>The driver registers three channels:</p>
<pre><code class="lang-c"><span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">iio_chan_spec</span> <span class="hljs-title">ms8607_channels</span>[] = {</span>
    {
        .type = IIO_PRESSURE,
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
    },
    {
        .type = IIO_TEMP,
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
    },
    {
        .type = IIO_HUMIDITYRELATIVE,
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
    },
};
</code></pre>
<p>Userspace reads from <code>/sys/bus/iio/devices/iio:device0/</code>:</p>
<ul>
<li><p><code>in_pressure_raw</code>: 97983 → 979.83 mbar</p>
</li>
<li><p><code>in_temp_raw</code>: 2073 → 20.73°C</p>
</li>
<li><p><code>in_humidityrelative_raw</code>: 3051 → 30.51%RH</p>
</li>
</ul>
<h2 id="heading-testing">Testing</h2>
<p>An automated test script handles module loading and sensor validation:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
make clean &amp;&amp; make
sudo insmod main.ko

<span class="hljs-comment"># Find IIO device</span>
IIO_DEV=$(find /sys/bus/iio/devices/ -name <span class="hljs-string">"*ms8607*"</span>)

<span class="hljs-comment"># Read sensors</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Pressure: <span class="hljs-subst">$(cat $IIO_DEV/in_pressure_raw)</span> (raw)"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Temperature: <span class="hljs-subst">$(cat $IIO_DEV/in_temp_raw)</span> (raw)"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Humidity: <span class="hljs-subst">$(cat $IIO_DEV/in_humidityrelative_raw)</span> (raw)"</span>
</code></pre>
<p>All three sensors reported valid readings on hardware.</p>
<h2 id="heading-cicd-pipeline">CI/CD Pipeline</h2>
<p>GitHub Actions runs static analysis and device tree validation on every push:</p>
<ul>
<li><p><strong>checkpatch</strong>: Linux kernel coding style verification</p>
</li>
<li><p><strong>sparse</strong>: Static analyzer for kernel code</p>
</li>
<li><p><strong>cppcheck</strong>: Additional static analysis</p>
</li>
<li><p><strong>Device tree compilation</strong>: Validates overlay syntax</p>
</li>
</ul>
<p>ARM cross-compilation builds run on manual trigger or release tags. The workflow builds <code>vmlinux</code> before modules to ensure proper symbol resolution—building only <code>make modules</code> caused missing symbol errors in <code>modpost</code>.</p>
<h2 id="heading-platform-specific-issues">Platform-Specific Issues</h2>
<h3 id="heading-arm32-division">ARM32 Division</h3>
<p>The ARM32 kernel doesn't support 64-bit division. This issue showed up during CI cross-compilation—code that built fine on x86 failed with a link error on ARM:</p>
<pre><code class="lang-c"><span class="hljs-comment">// WRONG - link error on ARM32</span>
s64 temp = <span class="hljs-number">2345</span>;
dev_info(&amp;client-&gt;dev, <span class="hljs-string">"Temp: %lld°C\n"</span>, temp / <span class="hljs-number">100</span>);
<span class="hljs-comment">// ERROR: "__aeabi_ldivmod" undefined!</span>
</code></pre>
<p>Fix: cast to 32-bit before division:</p>
<pre><code class="lang-c"><span class="hljs-comment">// CORRECT</span>
s64 temp = <span class="hljs-number">2345</span>;
<span class="hljs-keyword">int</span> temp_int = (<span class="hljs-keyword">int</span>)temp;
dev_info(&amp;client-&gt;dev, <span class="hljs-string">"Temp: %d°C\n"</span>, temp_int / <span class="hljs-number">100</span>);
</code></pre>
<h2 id="heading-resources">Resources</h2>
<p><strong>Hardware &amp; Datasheets</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&amp;DocNm=MS8607-02BA01&amp;DocType=DS&amp;DocLang=English">MS8607 Datasheet</a></p>
</li>
<li><p><a target="_blank" href="https://www.adafruit.com/product/4716">Adafruit MS8607 Breakout</a></p>
</li>
<li><p><a target="_blank" href="https://docs.beagleboard.org/">BeagleBone Black Documentation</a></p>
</li>
</ul>
<p><strong>Linux Kernel Documentation</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://docs.kernel.org/driver-api/iio/">IIO Subsystem</a></p>
</li>
<li><p><a target="_blank" href="https://docs.kernel.org/i2c/writing-clients.html">I2C Subsystem</a></p>
</li>
<li><p><a target="_blank" href="https://docs.kernel.org/devicetree/usage-model.html">Device Tree Usage</a></p>
</li>
</ul>
<p><strong>Code References</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/billvanleeuwen424/ms8607-driver">MS8607 Driver Repository</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/torvalds/linux/blob/master/drivers/iio/pressure/ms5637.c">MS5637 Driver</a> (similar sensor)</p>
</li>
<li><p><a target="_blank" href="https://github.com/beagleboard/bb.org-overlays">BeagleBone Device Tree Overlays</a></p>
</li>
</ul>
<p><strong>Learning Resources</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://bootlin.com/training/">Bootlin Training Materials</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=Nz6aBffv-Ek">Bootlin Device Tree 101</a></p>
</li>
</ul>
<hr />
<p>This project gave me hands-on experience with the driver layer of embedded Linux—something I haven't yet had the chance to work with. Writing a kernel module from scratch meant learning more about device trees, IIO subsystem internals, I2C protocol details, and platform-specific constraints like ARM32 arithmetic limitations.</p>
<p>If you're interested in embedded Linux development, the full source code and documentation are available in the <a target="_blank" href="https://github.com/billvanleeuwen424/ms8607-driver">GitHub repository</a>.</p>
<p>Thanks for reading! :)</p>
]]></content:encoded></item><item><title><![CDATA[My Journey Building a Rust TCP Server with an AI Assistant]]></title><description><![CDATA[Project link
Intro
AI is all the hype these days. Where I currently work, we are just getting started accepting the world of AI - primarily for log analysis, and use of co-pilot in our editors.
I wanted to try out using an AI agent. I utilize Zed for...]]></description><link>https://blog.billvanleeuwen.ca/my-journey-building-a-rust-tcp-server-with-an-ai-assistant</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/my-journey-building-a-rust-tcp-server-with-an-ai-assistant</guid><category><![CDATA[Rust]]></category><category><![CDATA[AI Agent Development]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Thu, 03 Jul 2025 19:21:59 GMT</pubDate><content:encoded><![CDATA[<p><a target="_blank" href="https://github.com/billvanleeuwen424/ai_gen_tcp_server">Project link</a></p>
<h2 id="heading-intro">Intro</h2>
<p>AI is all the hype these days. Where I currently work, we are just getting started accepting the world of AI - primarily for log analysis, and use of co-pilot in our editors.</p>
<p>I wanted to try out using an AI agent. I utilize <a target="_blank" href="https://zed.dev/">Zed</a> for any personal projects. It has beautiful integration for AI Agents.</p>
<p>To be clear with the reader, I don't fully understand what an 'AI agent' really is. I understand that it can modify your source code files, as well as run terminal commands (this is super cool by the way. will talk more on this later). But outside of this, I don’t know what it means for something to be 'agentic'.</p>
<h2 id="heading-how-did-it-work">How did it work?</h2>
<p>I'm utilizing Gemini for this, not for any particular reason. I started simple, asking the agent to generate me in Rust a simple TCP server which reverses any strings sent to it.</p>
<p>I wanted to run this in Docker, <em>so I asked</em>. It created a <a target="_blank" href="https://github.com/billvanleeuwen424/ai_gen_tcp_server/commit/cd85eb47c5bc5859524f2e4507e4b62f31237b89">docker file, and built the container!</a></p>
<h2 id="heading-what-amazed-me-most">What Amazed Me Most</h2>
<p>This AI Agent even helped debug system level issues. It really seemed like it was thinking along with me. Starting out, it bound to <code>127.0.0.1</code> (<a target="_blank" href="http://localhost">localhost</a>).</p>
<p><code>let listener = TcpListener::bind("127.0.0.1:8081").unwrap();</code></p>
<p>This didn’t allow me to connect to the server. I was able to debug this with the agent. It added extra logs to the project, and when it couldn't see those in the log output I provided, it suggested a fix which worked! Instead, we needed to bind to <code>0.0.0.0</code> (all interfaces). Wow!</p>
<p>This whole process took maybe 30 minutes. I would humbly say I’m still a beginner with Rust, and this project might have taken me 3-4 times as long to do without this tool.</p>
<h2 id="heading-outro">Outro</h2>
<p>As this journey concludes, I can confidently say that venturing into AI-assisted development has been an incredibly rewarding experience. I'm genuinely happy to have tried this new approach, and I believe it has significantly broadened my perspective on how we can build software more efficiently and intelligently. I hope this blog post has provided some valuable insights into the process!</p>
<p><strong>The last paragraph was written by the Agent if you couldn’t tell ;)</strong></p>
]]></content:encoded></item><item><title><![CDATA[Crafting a 'Hello World' in Rust for the ESP-32: A Step-by-Step Guide]]></title><description><![CDATA[Jumping into embedded programming with Rust is a daunting challenge. I’ve written this blog post to help get you started. I’ll be showing you how to get the most basic of code, the ‘Hello world!’ running on the ESP-32, in Rust.
To write this post I’v...]]></description><link>https://blog.billvanleeuwen.ca/crafting-a-hello-world-in-rust-for-the-esp-32-a-step-by-step-guide</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/crafting-a-hello-world-in-rust-for-the-esp-32-a-step-by-step-guide</guid><category><![CDATA[Rust]]></category><category><![CDATA[embedded]]></category><category><![CDATA[ESP32]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Sun, 05 Jan 2025 16:24:45 GMT</pubDate><content:encoded><![CDATA[<p>Jumping into embedded programming with Rust is a daunting challenge. I’ve written this blog post to help get you started. I’ll be showing you how to get the most basic of code, the ‘Hello world!’ running on the ESP-32, in Rust.</p>
<p>To write this post I’ve distilled information from <a target="_blank" href="https://docs.esp-rs.org/book/">The Rust on ESP Book</a> (licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/legalcode">CC-BY-SA v4.0</a>)<a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/legalcode">, and I highl</a>y recommend giving it a read, especially if this topic interests you, as it trumps this blog post in detail and thoroughness.</p>
<h2 id="heading-setup">Setup</h2>
<p>Plug your ESP-32 in to a USB port on your machine. A light should turn on and you should now be able to see the serial port in your terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092715471/7a72af36-9ef0-4aa3-9558-65bc2473ee26.jpeg" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">ls /dev/ttyUSB0
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092622768/bceefe46-880c-4ddf-af9f-b4db39ad3d6a.png" alt class="image--center mx-auto" /></p>
<p>your serial port name <em>may</em> be different here, this just happens to be mine.</p>
<h2 id="heading-configure-your-host-system">Configure Your Host System</h2>
<p>add yourself to the tty and dialout group. You’ll need this to be able to interact with the board over its serial connection.</p>
<pre><code class="lang-bash">sudo usermod -aG dialout &lt;youruser&gt;
sudo usermod -aG tty &lt;youruser&gt;
</code></pre>
<p>After this, logout and log back in to your machine, check that you are a member of these groups with <code>groups</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092606530/083a2207-af62-4b2c-a413-ffe4b4d71118.png" alt class="image--center mx-auto" /></p>
<p>On your host system install cargo generate. We’ll be using this to generate a template, meaning all the extra code and configuration we need for the ESP-32.</p>
<pre><code class="lang-bash">cargo install cargo-generate
</code></pre>
<p>Note: on my system, I had to install <code>openssl-dev</code> on my host to compile past errors.</p>
<h2 id="heading-generate-your-code">Generate Your Code</h2>
<p>Now generate the required template for our system.</p>
<pre><code class="lang-bash">cargo generate esp-rs/esp-idf-template cargo
</code></pre>
<p>you'll see a TUI menu, set the project name to <code>hello_world</code>, the MCU to <code>esp32</code>, and don’t configure advanced options.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092585902/d871e544-fda6-4976-a7a7-bf5b4dbc0dd7.png" alt class="image--center mx-auto" /></p>
<p>You can read this section of <a target="_blank" href="https://docs.esp-rs.org/book/writing-your-own-application/generate-project/esp-idf-template.html">the tutorial</a> I mentioned above if you want to know more about the generator.</p>
<p>You should now see some new files! The most important of which is <code>src/</code><a target="_blank" href="http://main.rs"><code>main.rs</code></a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092577180/95783472-41a4-404d-864f-5859fbfddd6d.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-create-build-environment">Create Build Environment</h2>
<p>Now we need to create the build environment. We’ll be using the container provided by <a target="_blank" href="https://hub.docker.com/r/espressif/idf-rust/">espressif</a>, since it already has all the configurations and packages requires.</p>
<p>Change directories into your generated project, pull the container, and start it:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> hello_world
docker pull espressif/idf-rust:all_1.83.0.1
docker run -it -v <span class="hljs-variable">$PWD</span>:/home/esp/hello_world  espressif/idf-rust:all_1.83.0.1 bash
</code></pre>
<p>the above docker command will start an interactive shell inside the container, and mount a volume of your generated project inside of it.</p>
<p>You should have now have a shell inside the container:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092566806/91f005e0-2e79-4deb-a1f1-b49fe4db63a7.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-build-flash-and-run-code">Build, Flash and Run, Code</h2>
<p>In the <em>container shell</em>, cd into the <code>hello_world</code> directory and build the code as you would any other Rust project:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> hello_world
cargo build
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092557888/08d58820-09d3-42d3-a080-b638cd29cda4.png" alt class="image--center mx-auto" /></p>
<p>After some time, your build will finish.</p>
<p>Back on the hosts shell, install espflash. This is a neat little tool that makes flashing the ESP32 as easy as 01,10,11 :)</p>
<pre><code class="lang-bash">cargo install espflash
</code></pre>
<p>For install errors, I had to install <code>systemd-devel</code> for the this to work.</p>
<p>Now that we're installed, let's flash our code to the board!</p>
<pre><code class="lang-bash">espflash flash target/xtensa-esp32-espidf/debug/hello_world --monitor
</code></pre>
<p>This command will both flash to the board, as well as monitor on the serial port for any logging.</p>
<p>The ESP-32 will automatically run your code on boot, so you wont need to do anything else here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092538038/9ff9c8b1-21d8-4423-97f3-f6bec65ab922.png" alt class="image--center mx-auto" /></p>
<p>Success! Now you can play around on your own here. I personally just like to set up an infinite loop for fun :)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736092525722/24b0203a-3fe6-45c4-8bc2-5adefc943f61.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that you have a system set up to run Rust code on the ESP-32, the world is your oyster! I urge you to find more examples to broaden your horizon, or just experiment a little! Take a look at the <a target="_blank" href="https://docs.esp-rs.org/"><strong>esp-rs</strong></a> website for some other reccomendations, and good luck! 🫡</p>
<h2 id="heading-footnote">Footnote</h2>
<p>This post could not have been written without help from <a target="_blank" href="https://docs.esp-rs.org/book/">The Rust on ESP Book</a>. I’ve distilled information from that book, as well as included some of my own. That book is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/legalcode">CC-BY-SA v4.0</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Exploring Rust: A C Programmers Insight]]></title><description><![CDATA[Much has been said of Rust in the last few years, and thus I will not add to the endless byte stream of “What Rust is and why it is better than everything else!”. This blog will assume at a basic leve]]></description><link>https://blog.billvanleeuwen.ca/exploring-rust-a-juniour-c-programmers-insight</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/exploring-rust-a-juniour-c-programmers-insight</guid><category><![CDATA[Rust]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Sat, 04 Jan 2025 02:44:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735956368128/933c7768-7ad8-4883-a6dc-c9441d67148b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Much has been said of Rust in the last few years, and thus I will not add to the endless byte stream of “What Rust is and why it is better than everything else!”. This blog will assume at a basic level that you know what Rust is, and you're interested in hearing my opinion.</p>
<p>I currently work at <a href="https://www.ciena.com/">Ciena</a> as a New Grad Embedded Software Engineer. For the last year or so, I've primarily written in C. I've started to learn the language, but I'm no expert. I’ve always enjoyed learning new things, and my friend <a href="https://matthew-brown.net/">Matt Brown</a> has encouraged me to try Rust out.</p>
<h2>How Did I Learn?</h2>
<p>I first followed loosely along with the <a href="https://doc.rust-lang.org/book/title-page.html">Rust book</a>, and completed the Async Web Server <a href="https://github.com/billvanleeuwen424/hello-webserver-rust">Final Project</a>. It was very nice to have a guided tour through some of the more interesting parts of the language.</p>
<p>Next, I wanted to create a CLI tool - so as a true Linux nerd I copycatted the greatest program known to man… <a href="https://github.com/billvanleeuwen424/neofetch-lite-rust">NEOFETCH!</a></p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735957222160/b858102c-363b-4c7a-8d14-819a8564fefd.png" alt="" style="display:block;margin:0 auto" />

<p>Mine is much lighter than the original, but you get the point.</p>
<p>I’m still by no means an expert at Rust - it’s true what folks say; the learning curve is very steep.</p>
<h2>What Do I Like About Rust?</h2>
<p>I loved the 'nice things' that Rust comes with: rust-fmt, the compile messages, and a built-in package manager. These are all things that folks like me in older software environments do not get to enjoy. Because of this, I found myself having a tonne of fun writing Rust.</p>
<p>This might be some reason why Rust is always <a href="https://survey.stackoverflow.co/2024/technology#admired-and-desired">the most admired/loved language of the year</a>. It’s young engineers like myself coming from things like C/C++ knowing that there must be a better way to work out there.</p>
<p>In terms of language features, I loved the way the compiler <em>forces</em> you to handle all situations. I liked <a href="https://doc.rust-lang.org/rust-by-example/flow_control/match.html">match statements</a> in favour of switch statements or if-else tree’s in C. Writing these on my own was when the gears turned and I understood why Rust could be important to use in a safety-critical environment.</p>
<pre><code class="language-rust">fn main() {
    let test_int = 1;
    match test_int {
        1 =&gt; {
            println!("The line is 1!");
        }
        _ =&gt; {
            println!("default value!")
        }
    }
}
</code></pre>
<h2>What I’m Struggling With</h2>
<p>Like many folks, I’m still struggling with the different types of ‘strings’ and when I should use what (<code>String</code> vs <code>&amp;str</code>). It seems like I’m not the <a href="https://users.rust-lang.org/t/understanding-when-to-use-string-vs-str/103746">only one</a> which is nice to know.</p>
<p>As well in general, just learning a new language. Especially one like Rust which has a little bit of it’s own spice in terms of what the syntax looks like.</p>
<h2>Conclusion</h2>
<p>In general, I have enjoyed my time with Rust so far, and look forward to working with it some more :) stay tuned for any future blog posts on any Rust projects I write. I’d personally love to get into some Embedded Rust.</p>
]]></content:encoded></item><item><title><![CDATA[Writing and Inserting a 'Hello World' Kernel Module for the Beaglebone Black (Buildroot)]]></title><description><![CDATA[This blog follows my previous one on Setting Up Networking and an HTTP Server on the BeagleBone Black with Buildroot.
This is part of my independent study course on Embedded Linux and follows from many of my past blogs.
My final unit is an intro to D...]]></description><link>https://blog.billvanleeuwen.ca/writing-and-inserting-a-hello-world-kernel-module-for-the-beaglebone-black-buildroot</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/writing-and-inserting-a-hello-world-kernel-module-for-the-beaglebone-black-buildroot</guid><category><![CDATA[beaglebone black]]></category><category><![CDATA[embedded linux]]></category><category><![CDATA[linux kernel]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Sun, 19 Mar 2023 17:30:36 GMT</pubDate><content:encoded><![CDATA[<p>This blog follows my previous one on <a target="_blank" href="https://blog.billvanleeuwen.ca/setting-up-networking-and-an-http-server-on-the-beaglebone-black-with-buildroot">Setting Up Networking and an HTTP Server on the BeagleBone Black with Buildroot</a>.</p>
<p>This is part of my independent study course on Embedded Linux and follows from many of my past blogs.</p>
<p>My final unit is an intro to Drivers for Linux systems. This blog post will only be on the practical methods of how to write and use a basic driver for a Linux system. Much of the theoretical knowledge from this can be found by reading the free book <a target="_blank" href="https://lwn.net/Kernel/LDD3/">Linux Device Drivers, Third Edition</a>.</p>
<h2 id="heading-hello-world">Hello World!</h2>
<p>I assume that you, the reader, have taken at least one programming course (It would be quite silly if you were looking to program and insert a Linux Kernel Module if you hadn't). So as you know, 'Hello world!' is the first exercise many of us follow when trying something new. So, we're going to keep that tradition alive with our first Kernel Module.</p>
<p>Our code for this exercise will be basic familiar C, with some new macros and header files you may not have used before:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;linux/module.h&gt;    /* Needed by all modules */</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;linux/kernel.h&gt;    /* Needed for KERN_INFO */</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">init_module</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{
    printk(KERN_INFO <span class="hljs-string">"Hello World!\n"</span>);

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">cleanup_module</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>{
    printk(KERN_INFO <span class="hljs-string">"Goodbye World.\n"</span>);
}

MODULE_LICENSE(<span class="hljs-string">"GPL"</span>);
</code></pre>
<p>As you see, <code>main()</code> has been replaced by <code>init_module()</code>. They essentially act as the same thing, <code>init_module()</code> is the entry point for the file once it has been inserted into the kernel.</p>
<p><code>printk</code> looks strikingly similar to <code>printf</code> with the addition of the <code>KERNEL_INFO</code> macro. This macro can be one of many things. One could find all of the options here, and more about printk on <a target="_blank" href="https://www.kernel.org/doc/html/next/core-api/printk-basics.html">this kernel.org page</a>.</p>
<p>Copy this code, and name the file <code>hello.c</code></p>
<h2 id="heading-compiling-this-code">Compiling This Code</h2>
<p>If you've been following my other <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-minimal-linux-system-for-the-beaglebone-black-with-buildroot">blog posts</a>, you might know that there is some setup that needs to be done to compile this code for our ARM board. The additional trouble comes here when we need special Linux header files to link to our code (<code>linux/module.h</code> and <code>linux/kernel.h</code>).</p>
<h3 id="heading-the-makefile">The Makefile</h3>
<p>A Makefile will make this considerably easier, as there are a few compile steps needed:</p>
<pre><code class="lang-makefile">CC = <span class="hljs-variable">$(CROSS_COMPILE)</span>gcc

obj-m := hello.o
KDIR := ~/buildroot/output/build/linux-6.0.9

<span class="hljs-section">all:</span>
    <span class="hljs-variable">$(MAKE)</span> -C <span class="hljs-variable">$(KDIR)</span> M=<span class="hljs-variable">$(PWD)</span>
</code></pre>
<p>Create a file named <code>Makefile</code> in the same directory as your code file, and copy this into it.</p>
<p>You will need to change the KDIR variable to be specific to your setup. This variable should be the path to the Linux source files that buildroot compiles for your board. These can be found at <code>buildroot/output/build/linux-YOURVERSION</code>. This points our compiler to the object files we need to link against.</p>
<p>If you were writing modules for your desktop computer, KDIR should point at the kernel headers specific to the version your PC is running on. But this is just an interesting tidbit, and we are writing for only our board today.</p>
<h3 id="heading-the-cross-compiler">The Cross-compiler</h3>
<p>We want to use the same compiler that buildroot uses to compile all the programs and Linux kernel. It <em>might</em> be possible to use another ARM compiler, but when it comes to compiling for different boards, and all of the minute configurations that can be done to these compilers, let's play it safe and use the same one.</p>
<p>If you're following my configuration from my <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-minimal-linux-system-for-the-beaglebone-black-with-buildroot">earlier blog</a>, you can find your compiler in <code>buildroot/output/host/bin/</code>. The one we need is the <code>arm-none-linux-gnueabihf-gcc</code>.</p>
<p>We need to tell our Makefile to use this compiler, otherwise, it will default to the <code>gcc</code> we have installed on our Linux desktop.</p>
<p>To compile our code, run the following command in the directory which contains the code file, and Makefile (of course changing the path to be valid on your machine):</p>
<p><code>make CROSS_COMPILE=~/buildroot/output/host/bin/arm-none-linux-gnueabihf- ARCH=arm</code></p>
<p>We didn't include the <code>gcc</code> on the end, because that is implied with the Makefile</p>
<p>Running this, your code should compile, and you should see a bunch of new object files, but the most important one for us is the <code>hello.ko</code> file. This is a compiled kernel object file which we can use on our buildroot Beagelbone board.</p>
<h2 id="heading-inserting-the-kernel-module">Inserting The Kernel Module</h2>
<p>Copy this file onto the board. If you have the correct configuration, you can <code>scp</code> or <code>sftp</code> this file. Otherwise, you can copy this to the SD card.</p>
<p>In the terminal on the board, insert the module with <code>insmod hello.ko</code>. Check the kernel output with <code>cat /var/log/messages</code>. You should see your Hello World!</p>
<p>To remove this module, simply <code>rmmod hello.ko</code>. Check the output again and you'll see Goodbye world.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679246945807/52e5e215-c7d4-4f06-b9ec-50f2683e7faa.png" alt class="image--center mx-auto" /></p>
<p>Congratulations! You just wrote your first kernel code.</p>
]]></content:encoded></item><item><title><![CDATA[Debugging Code With GDB and Valgrind]]></title><description><![CDATA[For this project, I followed the GDB instructions from Bootlin and used Valgrind on one of my programs from my High-Performance Computing class.
Intro to GDB and Valgrind
GDB
GDB is a full-featured and open-source debugger. It is integrated into VSCo...]]></description><link>https://blog.billvanleeuwen.ca/debugging-code-with-gdb-and-valgrind</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/debugging-code-with-gdb-and-valgrind</guid><category><![CDATA[gdb]]></category><category><![CDATA[valgrind]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Fri, 10 Mar 2023 23:44:56 GMT</pubDate><content:encoded><![CDATA[<p>For this project, I followed the GDB <a target="_blank" href="https://bootlin.com/doc/training/debugging/debugging-labs.pdf">instructions</a> from <a target="_blank" href="https://bootlin.com/">Bootlin</a> and used Valgrind on one of my programs from my High-Performance Computing class.</p>
<h2 id="heading-intro-to-gdb-and-valgrind">Intro to GDB and Valgrind</h2>
<h3 id="heading-gdb">GDB</h3>
<p><a target="_blank" href="https://sourceware.org/gdb/">GDB</a> is a full-featured and open-source debugger. It is integrated into VSCode and given a very pretty front end.</p>
<p>It is possible to remote debug with VSCode and GDB, but often many embedded development environments run it in its natural form on the terminal.</p>
<h3 id="heading-valgrind">Valgrind</h3>
<p><a target="_blank" href="https://valgrind.org/">Valgrind</a> opposed to GDB is a runtime tool. It analyses the stack, heap and disassembly of the program to primarily find and report memory leaks.</p>
<p>It can be used for much more, including cache usage and miss reports, deadlocks and race conditions, and heap memory usage.</p>
<h2 id="heading-gdb-1">GDB</h2>
<h3 id="heading-packages">Packages</h3>
<p>I had to enable some settings in the buildroot menu for GDB to be present and working on the board:</p>
<ul>
<li><p>BR2_PACKAGE_HOST_GDB, in Toolchain | Build cross gdb for the host</p>
</li>
<li><p>BR2_PACKAGE_GDB, in Target packages | Debugging, profiling and benchmark | gdb</p>
</li>
<li><p>BR2_PACKAGE_GDB_SERVER, in Target packages | Debugging, profiling and benchmark | gdbserver</p>
</li>
<li><p>BR2_ENABLE_DEBUG, in Build options | build packages with debugging symbols</p>
<ul>
<li>This one specifically builds the included C libraries with debugging symbols.</li>
</ul>
</li>
</ul>
<h3 id="heading-running-the-code">Running the Code</h3>
<p>In order to connect to the board, and run gdb remotely, we need to run this command on the board:</p>
<pre><code class="lang-bash">gdbserver --multi :2000 ./linked_list
</code></pre>
<p>Which outputs:</p>
<pre><code class="lang-bash">Process ./linked_list created; pid = 168
Listening on port 2000
</code></pre>
<p>and then start gdb on our pc</p>
<pre><code class="lang-bash">gdb
</code></pre>
<p>Which when running, looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681684950587/6be9c0e1-1586-4e8f-b81b-27266322869b.png" alt class="image--center mx-auto" /></p>
<p>To connect to the board we need to run:</p>
<pre><code class="lang-bash">target extended-remote 192.168.1.100:2000
</code></pre>
<p>Where the IP address is that of the board, and the port 2000, is what we told GDB to use.</p>
<h3 id="heading-compiling-and-placing-on-board">Compiling and Placing On board</h3>
<p>We should compile this program using the cross-compiler provided by buildroot. It is found in <code>output/host/bin/arm-none-linux-gnueabihf-gcc</code> and we can add this to our PATH to make it easier and faster to compile our programs.</p>
<p>We need to do this because buildroot doesn't include a compiler when it builds the images. It is intended for final products mostly.</p>
<p>We can compile on our machine and sftp it over with:</p>
<pre><code class="lang-bash">sftp root@192.168.1.100
</code></pre>
<h3 id="heading-debugging">Debugging</h3>
<p>The most basic commands for GDB are:</p>
<ol>
<li><p><code>run</code> - starts the execution of the program being debugged.</p>
</li>
<li><p><code>break</code> - sets a breakpoint at a specified location in the program.</p>
</li>
<li><p><code>step</code> - executes the current line and stops at the next line in the source code.</p>
</li>
<li><p><code>next</code> - executes the current line and stops at the next line, but does not enter function calls.</p>
</li>
<li><p><code>continue</code> - resumes execution until the next breakpoint or until the program terminates.</p>
</li>
<li><p><code>print</code> - prints the value of a specified variable or expression.</p>
</li>
<li><p><code>backtrace</code> or <code>bt</code> - prints the stack trace of the program at the current point of execution.</p>
</li>
<li><p><code>list</code> - displays the source code around the current point of execution.</p>
</li>
<li><p><code>info</code> - displays various types of information about the program being debugged, such as registers, breakpoints, and threads.</p>
</li>
<li><p><code>quit</code> - exits GDB.</p>
</li>
</ol>
<p>we can use this to trace along our program like in vscode</p>
<p>I'll set a breakpoint at the 'main' function with <code>b main</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681684937781/6fb809f3-1395-4021-a713-9690d55fd75e.png" alt class="image--center mx-auto" /></p>
<p>and run the program, stepping with <code>next</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681684931833/76259062-4596-4498-8c58-0ca5ed857c95.png" alt class="image--center mx-auto" /></p>
<p>You can see that this follows along the code file that we have:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681684911326/23731cb7-8764-479e-b120-0161de93fcd9.png" alt class="image--center mx-auto" /></p>
<p>GDB also has a nice Text-User-Interface, or TUI that you can enter with Ctrl-X-A</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681684916610/bffaa1c0-18b1-4e53-9dc7-1861d91922f6.png" alt class="image--center mx-auto" /></p>
<p>Let's try out a few of these commands:</p>
<p>We can set breakpoints with 'b' and see them with the info command:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681684899803/1691f30e-a530-4670-89e7-29538e30f946.png" alt class="image--center mx-auto" /></p>
<p>And delete them with 'delete'</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681684888568/6a93b950-a3db-4acf-9266-275cb69cb13b.png" alt class="image--center mx-auto" /></p>
<p>There are many more commands, and gdb is one of those tools that can take time to master. This was just a simple lab, however.</p>
<h2 id="heading-valgrind-1">Valgrind</h2>
<p>I ran valgrind on a program I wrote in High-Performance Computing. This was a hastily poorly written program with little care for memory cleanup so I knew it would be leaky.</p>
<p>There isn't much to it. You can see output from valgrind with a summary of any memory leaks by running:</p>
<pre><code class="lang-bash">valgrind --leak-check=full ./program
</code></pre>
<p>Below is what is outputted (concatenated because it's super long):</p>
<pre><code class="lang-bash">==7144== Memcheck, a memory error detector

==7144== Copyright (C) 2002-2022, and GNU GPL<span class="hljs-string">'d, by Julian Seward et al.

==7144== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info

==7144== Command: mpirun -np 4 ./halo

==7144==

...

==7144==

==7144== LEAK SUMMARY:

==7144== definitely lost: 6,705 bytes in 24 blocks

==7144== indirectly lost: 31,491 bytes in 465 blocks

==7144== possibly lost: 0 bytes in 0 blocks

==7144== still reachable: 829 bytes in 21 blocks

==7144== suppressed: 0 bytes in 0 blocks

==7144== Reachable blocks (those to which a pointer was found) are not shown.

==7144== To see them, rerun with: --leak-check=full --show-leak-kinds=all

==7144==

==7144== For lists of detected and suppressed errors, rerun with: -s

==7144== ERROR SUMMARY: 21 errors from 21 contexts (suppressed: 0 from 0)</span>
</code></pre>
<p>As you can see, there are quite a few leaks in this program. It's run with MPI, and I didn't take into great consideration the cleaning up of the memory.</p>
]]></content:encoded></item><item><title><![CDATA[Setting Up Networking and an HTTP Server on the BeagleBone Black with Buildroot]]></title><description><![CDATA[This is a continuation of my previous blog where we set up a minimal Linux system for the BeagleBone Black with Buildroot.
Today we're going to set up networking and an HTTP server on the board to serve web pages.
Why might we want to do that?
Take f...]]></description><link>https://blog.billvanleeuwen.ca/setting-up-networking-and-an-http-server-on-the-beaglebone-black-with-buildroot</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/setting-up-networking-and-an-http-server-on-the-beaglebone-black-with-buildroot</guid><category><![CDATA[beaglebone black]]></category><category><![CDATA[embedded linux]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Sun, 05 Mar 2023 18:15:56 GMT</pubDate><content:encoded><![CDATA[<p>This is a continuation of my <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-minimal-linux-system-for-the-beaglebone-black-with-buildroot">previous blog</a> where we set up a minimal Linux system for the BeagleBone Black with Buildroot.</p>
<p>Today we're going to set up networking and an HTTP server on the board to serve web pages.</p>
<h4 id="heading-why-might-we-want-to-do-that">Why might we want to do that?</h4>
<p>Take for example any IoT device like this <a target="_blank" href="https://www.geappliances.com/ge/connected-appliances/washer-dryer-laundry.htm">Smart Washing Machine</a>, rather than running a cycle by having the user SSH into the Linux board and run scripts, one might run an HTTP server on the board and show a pretty website with nice features that anyone could use.</p>
<h2 id="heading-modify-the-buildroot-image">Modify the Buildroot Image</h2>
<p>We need to add some extra packages to our board, mainly the HTTP Server.</p>
<p>Just like last time, change into your buildroot directory, and run:</p>
<pre><code class="lang-plaintext">make menuconfig
</code></pre>
<p>You should see the familiar menuconfig page:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676467638475/6e8a79b6-0bb7-4b38-b233-fb8e4d49605f.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>In <em>Target Packages: Networking applications:</em></p>
<ul>
<li><p>Enable nginx, make sure http_server is enabled</p>
</li>
<li><p>Enable <a target="_blank" href="https://matt.ucc.asn.au/dropbear/dropbear.html">dropbear</a>. This is an SSH client that will be convenient for us.</p>
</li>
<li><p>Enable ifupdown scripts. These are init scripts courteously written for us to initialize our static network connection on the board.</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-set-up-networking">Set up Networking</h2>
<p>To connect our board to a network, we need a connection to our desktop.</p>
<p>Normally, you could do this by plugging your board into your router and letting it assign an IP address, but my router is pretty far from my desk so we'll have to use another method.</p>
<p><strong>Option 1</strong></p>
<p>If you have a network switch laying around, like this little Netgear one I have, you could use that:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677943581016/8c1da39a-073f-4cae-bde8-14e7021dd639.png" alt class="image--center mx-auto" /></p>
<p><strong>Option 2</strong></p>
<p>You could use a <a target="_blank" href="https://en.wikipedia.org/wiki/Ethernet_crossover_cable">Crossover Cable</a>. This will allow you to connect your desktop directly to the Beaglebone.</p>
<h3 id="heading-setting-ip-addresses">Setting IP Addresses</h3>
<p>Like I spoke about before, your router could just assign the board an IP address. This is because the router is running a <a target="_blank" href="https://www.infoblox.com/glossary/dhcp-server/">DCHP Server</a> that assigns IP's for every computer on your network.</p>
<p>Since we are connecting our PC directly to our board, this will be a separate network from your router and will require different configuration.</p>
<p>We could run a DCHP server on our Desktop to assign the board an IP, but because we're only connecting one thing to this network, that is certainly overkill.</p>
<p>We'll define a static address for our board in its <code>/etc/network/interfaces</code> file.</p>
<h4 id="heading-making-an-overlay-directory">Making an Overlay Directory</h4>
<p>Instead of SSH'ing into the board every time we create a new image to modify this file, we can use an overlay file. This is an option in the buildroot menuconfig to allow us to add things into the image each time it builds.</p>
<p>In the buildroot directory, create and overlay directory, and fill it with the directories and files we need:</p>
<pre><code class="lang-bash">mkdir -p overlay/etc/network
touch overlay/etc/network/interfaces
vi overlay/etc/network/interfaces
</code></pre>
<p>In this vi window, paste:</p>
<pre><code class="lang-plaintext">auto eth0
iface eth0 inet static
    address 192.168.1.100
    gateway 192.168.1.1
    netmask 255.255.255.0
</code></pre>
<p>Here what we are doing, is setting our ethernet interface, <code>eth0</code>, to have a static ip address of <code>192.168.1.100</code>, and giving it the gateway of <code>192.168.1.1</code>.</p>
<p>Now enter the menuconfig, and in System Configuration, set the Root filesystem overlay directory to <code>./overlay</code></p>
<p>Now run <code>make</code> to build this new image, flash it onto your SD card when you're finished.</p>
<p>Plug the board in and boot it holding the USR button as usual. Plug your crossover cable or switch into both the board and your desktop.</p>
<p>In Settings, if you're running the GNOME Desktop Environment, go into network. You won't see a connection to your board yet, because you havent configured the static IP for your desktop.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677945211966/99309519-7a0f-444a-9fc4-8c4fdc4ff532.png" alt class="image--center mx-auto" /></p>
<p>Add a Wired network, and set your settings as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677945430034/b05e804d-61e1-426a-a07a-043bc8b0beb7.png" alt class="image--center mx-auto" /></p>
<p>The last set of numbers on your address can be whatever you'd like (except the IP you used for the beaglebone), I just used <code>192.168.1.45</code>.</p>
<p>Save this network, and you should now see that you're connected to a wired network!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677945535864/26a7b6b5-1e03-4f28-b3ce-3caadaa19552.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-ssh">SSH</h2>
<p>Now we should be able to ssh into our board.</p>
<pre><code class="lang-bash">ssh root@192.168.1.100
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677945631864/3eb16164-1762-45f6-b15c-3a9d89209a78.png" alt class="image--center mx-auto" /></p>
<p>You'll notice ssh is acting very sluggish upon connection. There is something we can disable on the image to fix this.</p>
<p>In the menuconfig, navigate to the dropbear package. Inside this, disable reverse DNS Lookups.</p>
<p><a target="_blank" href="https://www.cisco.com/c/en/us/support/docs/switches/nexus-5000-series-switches/211983-Delay-Before-Password-Prompt-Appears-whi.pdf">Reverse DNS Lookup</a> is a security feature, normally used to verify the authenticity of connections. But since our beaglebone isn't connected to any DNS server it will hang here as it screams out into nothing, waiting for a return from a non-existent DNS server.</p>
<p>Build this image and put it onto your card, and SSH access should be fast now!</p>
<h2 id="heading-serving-web-pages">Serving Web Pages</h2>
<p>Busybox init handles a lot of the work for us here. Because we enabled nginx, buildroot has assumed that we want it to run each time on startup.</p>
<p>With the board booted up, and network cable connected, you should be able to go directly to <code>192.168.1.100</code> in your browser and get the nginx configure page:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678035172629/c4c965ad-bab7-4f36-9a7b-1be09653fd6b.png" alt class="image--center mx-auto" /></p>
<p>According to</p>
<p>Next, we need to provide some basic configuration to NGINX to serve our custom pages. In the <a target="_blank" href="https://nginx.org/en/docs/beginners_guide.html">The NGINX Beginners Guide</a>, we learn that the configuration file for nginx is in <code>/etc/nginx/nginx.conf</code> and has a relatively simple configuration process.</p>
<p>Instead of doing this on our board, where every time we reinstall an image we'd have to repeat this process, lets automate this through the use of the overlay directory.</p>
<p>Back in your buildroot diretory, cd into your overlay directory.</p>
<pre><code class="lang-bash">mkdir -p etc/nginx/
touch etc/nginx/nginx.conf
</code></pre>
<p>In a text editor, enter the following simple config into <code>nginx.conf</code> :</p>
<pre><code class="lang-plaintext">worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root  /data/www;
            index  index.html;
        }
    }
}
</code></pre>
<p>This tells nginx we want to serve out of <code>/data/www</code> which is the recommended location in the aforementioned beginner's guide.</p>
<p>Create this directory in the overlay as well:</p>
<pre><code class="lang-bash">mkdir -p data/www
touch data/www/index.html
</code></pre>
<p>In a text editor, let's add a "Hello world page" to demonstrate a working embedded web server:</p>
<pre><code class="lang-javascript">&lt;!DOCTYPE HTML&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    alert( <span class="hljs-string">'Hello world from the BeagleBone Black!'</span> );
    <span class="hljs-built_in">document</span>.write(<span class="hljs-string">'Hello world from the BeagleBone Black!'</span>);
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>After this, run <code>make</code> to build the image, flash it to the board, and boot it familiarly.</p>
<p>Navigate to the board's address in the browser, and:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678040002642/12477826-1356-447a-bb7c-428c9c34c859.png" alt class="image--center mx-auto" /></p>
<p>Success! We can serve web pages from the beaglebone to your desktop!</p>
]]></content:encoded></item><item><title><![CDATA[Creating a Minimal Linux System for the BeagleBone Black with Buildroot]]></title><description><![CDATA[If you've been following my earlier blogs, this is a continuation of my independent study course on Embedded Linux. In the previous blogs, I covered building a Linux system from scratch. But now it's time to upgrade to a build system.
I'm going to be...]]></description><link>https://blog.billvanleeuwen.ca/creating-a-minimal-linux-system-for-the-beaglebone-black-with-buildroot</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/creating-a-minimal-linux-system-for-the-beaglebone-black-with-buildroot</guid><category><![CDATA[embedded linux]]></category><category><![CDATA[buildroot]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Wed, 15 Feb 2023 15:37:22 GMT</pubDate><content:encoded><![CDATA[<p>If you've been following my earlier blogs, this is a continuation of my independent study course on Embedded Linux. In the previous blogs, I covered building a Linux system from scratch. But now it's time to upgrade to a build system.</p>
<p>I'm going to be using <a target="_blank" href="https://buildroot.org/">Buildroot</a> in this tutorial. I chose Buildroot as it is one of the less complex and more widely used build systems in the embedded Linux space. <a target="_blank" href="https://www.yoctoproject.org/">Yocto</a> is arguably better for a production scenario but takes much longer to master due to its complexity. Buildroot is simple but lacks many of the bells and whistles that Yocto has.</p>
<p>Much of this blog is based on <a target="_blank" href="https://bootlin.com/training/buildroot/">bootlin's training documentation</a>, so it may be more useful for you to follow along with that as well as this blog.</p>
<h2 id="heading-what-is-a-build-system">What is a Build System?</h2>
<p>A build system is a lot of things and can look very different depending on the project. A build system in its easiest description is translating source code into binary files to be run on a system.</p>
<p>A simple build system could be a single makefile that compiles a single C program. Example below:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>{
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Hello World!\n"</span>);
</code></pre>
<pre><code class="lang-make">CC=gcc

hello:
        $(CC) hello.c -o hello
</code></pre>
<p>This is likely one of the simplest forms of build systems possible. It might almost be stretching it calling it a 'system' because of how minimal it is.</p>
<p>Buildroot is similar to this (but much much more complex). It does what this simple makefile does, except it compiles the Linux kernel, bootloader, any modifications you have, and many more, all according to the configurations you input.</p>
<p>Embedded Linux build systems automate so much that building from scratch is essentially obsolete except in some very interesting edge cases.</p>
<h2 id="heading-getting-buildroot">Getting Buildroot</h2>
<p>First, as always, clone the git repository:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://git.buildroot.net/buildroot
</code></pre>
<p>Switch into the cloned repo, and checkout the newest build</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> buildroot 
git checkout 2022.11
</code></pre>
<h2 id="heading-configuring-buildroot">Configuring Buildroot</h2>
<p>Buildroot uses the same menuconfig we saw in earlier blog's that crosstool and the Linux kernel does, so enter that with:</p>
<pre><code class="lang-plaintext">make menuconfig
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676467638475/6e8a79b6-0bb7-4b38-b233-fb8e4d49605f.png" alt class="image--center mx-auto" /></p>
<p>I'm closely following <a target="_blank" href="https://bootlin.com/doc/training/buildroot/buildroot-labs.pdf">Buildroot's Training Document here</a> With the largest change being that my BeagleBone is the non-wireless version, and thus uses a different device tree.</p>
<p>Do experiment with these options on your own time, or take some time to see what other options are available in the menuconfig. There are quite a few interesting options that are easy to implement.</p>
<ul>
<li><p>In <em>Target Options</em>:</p>
<ul>
<li><p>Select <code>ARM (little endian)</code> as <em>the Target Architecture</em></p>
</li>
<li><p>Select <code>cortex-A8</code> as the <em>Target Architecture Variant</em></p>
</li>
</ul>
</li>
<li><p>In <em>Toolchain:</em></p>
<ul>
<li><p>Set toolchain type to <code>External toolchain</code> . (This will save us a lot on build time).</p>
</li>
<li><p>Set the <em>Toolchain</em> under Toolchain External Options as <code>ARM 2021.07</code> .</p>
</li>
</ul>
</li>
<li><p>In <em>System Configuration:</em></p>
<ul>
<li><p>Set the <em>System hostname</em> to something of your preference. I used <code>billbeaglebone</code> .</p>
</li>
<li><p>Set the <em>System banner</em> as well to anything of interest. This is a line of text that will print every time you turn the system on. Mine is <code>Bill's Embedded Linux!</code></p>
</li>
<li><p><em>Enable root login with password</em> and set this password.</p>
</li>
</ul>
</li>
<li><p>In <em>Kernel:</em></p>
<ul>
<li><p>Enable <em>Linux Kernel</em>, the default should be the newest kernel (at the time of reading 6.0), this is fine for our use.</p>
</li>
<li><p>Define the <em>Defconfig name</em> as <code>omap2plus</code>.</p>
</li>
<li><p>Make sure the <em>Kernel binary format</em> is <code>zImage</code> .</p>
</li>
<li><p>Define the <em>In-tree Device Tree Source File name</em> as <code>am335x-boneblack</code> .</p>
</li>
<li><p>Enable <em>Needs host OpenSSL</em></p>
</li>
</ul>
</li>
<li><p>In <em>Target Packages:</em></p>
<ul>
<li><p>Enable <em>BusyBox.</em></p>
</li>
<li><p><strong>Optional:</strong> For a later blog, we will be debugging a program on the board using <a target="_blank" href="https://www.sourceware.org/gdb/">GDB</a> and <a target="_blank" href="https://valgrind.org/">Valgrind</a>. In <em>Debugging, profiling and benchmark</em> enable <code>GDB</code> and <code>gdbserver</code>, as well as <code>valgrind</code> .</p>
</li>
<li><p><strong>Optional:</strong> in <em>Networking applications</em> enable <a target="_blank" href="https://matt.ucc.asn.au/dropbear/dropbear.html">dropbear</a>. This is an SSH client that will be convenient to use later.</p>
</li>
<li><p><strong>Optional:</strong> For a little fun, in <em>Games</em> enable <code>ascii_invaders</code> .</p>
</li>
<li><p>Take a look around here at all the packages you can include so simply with Buildroot. If you followed the <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-cross-compiling-toolchain-for-beaglebone-black-with-crosstool-ng">last blog series</a> on creating an embedded Linux system from scratch, you might appreciate just how easy this is.</p>
</li>
</ul>
</li>
<li><p>In <em>Bootloaders:</em></p>
<ul>
<li><p>Enable <em>U-Boot</em>.</p>
</li>
<li><p>Define the <em>U-Boot configuration</em> as <code>am335x_evm</code> .</p>
</li>
<li><p>Set the <em>Build system</em> <code>Kconfig</code>.</p>
</li>
<li><p>Check that the <em>U-Boot Version</em> is set <code>2022.04</code> .</p>
</li>
<li><p>In <em>U-Boot binary format</em>, enable only <code>u-boot.img</code> .</p>
</li>
<li><p>Enable <em>Install U-Boot SPL binary image</em>, and set <em>U-boot SPL/TPL binary image name(s)</em> to <code>MLO</code> .</p>
</li>
</ul>
</li>
</ul>
<p>This finishes our configuration! Go ahead and save before exiting.</p>
<h2 id="heading-building-your-system">Building Your System</h2>
<p>For curiosity, Bootlin notes we should save the build log. If you don't care about this, you can just run <code>make</code>. But if you're interested like I am to see the build log, run <code>make 2&gt;&amp;1 | tee build.log</code> which will save the make and terminal logs to a build.log file.</p>
<p>The first time you build will take a while. Skip to 'Prepping the SD Card' in the interest of time.</p>
<p>Once the build is done, and you've dealt with any errors that may have come up (I had to install <code>perl</code> on my system), you should see these output files in the <code>output/images</code> directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676472598333/3b139ada-fb0b-42e8-b520-9c7ac338865e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-prepping-the-sd-card">Prepping the SD Card</h2>
<p>You should use a good SD card for this. At first I tried the <a target="_blank" href="https://www.kingston.com/en/memory-cards/canvas-select-plus-microsd-card">Kingston CANVAS Select Plus</a>, but experienced issues with the read/write speeds. I upgraded to the <a target="_blank" href="https://www.westerndigital.com/en-ca/products/memory-cards/sandisk-extreme-uhs-i-microsd#SDSQXAF-032G-GN6MA">SanDisk Extreme</a> and had no issues.</p>
<p>We need to create two partitions on our card. You can use command line tools, or something easy like <a target="_blank" href="https://gparted.org/">GParted</a>.</p>
<p>Create two partitions, the first a FAT32 filesystem with 128Mib, and the second a ext filesystem taking up the remaining space on the card.</p>
<p>You should end up with partitions looking similar to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676473971525/6f56e762-8ee6-473b-9dd0-3dce49bbb760.png" alt class="image--center mx-auto" /></p>
<p>Label the partitions as I did for ease of use, and set the boot flag on the <code>boot</code> partition by left-clicking, and selecting <code>Manage flags</code> .</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676474007113/ef21175e-320d-404d-9e43-948f4dda0df0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-prepping-our-linux-system">Prepping Our Linux System</h2>
<p>Once the build finishes, and you have your SD Card formatted, we are ready to move our files over to the BeagleBone.</p>
<p>Follow the steps in my <a target="_blank" href="https://blog.billvanleeuwen.ca/porting-u-boot-onto-the-beaglebone">earlier blog</a> to connect a serial adapter, and install <code>picocom</code> .</p>
<p>Copy the files from the <code>output/images</code> directory onto the <code>boot</code> partition like so:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#On Fedora Linux, the SD card is mounted at /run/media/$USER/partitionname, this may be different depending on your distro.</span>
cp MLO u-boot.img zImage am335x-boneblack.dtb /run/media/<span class="hljs-variable">$USER</span>/boot/
</code></pre>
<p>We can create a file to give U-Boot commands without setting the bootloader manually. Create a folder and file in the <code>boot</code> partition:</p>
<pre><code class="lang-bash">mkdir extlinux &amp;&amp; touch extlinux/extlinux.conf
</code></pre>
<p>Fill this file with the following text:</p>
<pre><code class="lang-plaintext">label buildroot
        kernel /zImage
        devicetree /am335x-boneblack.dtb
        append console=ttyO0,115200 root=/dev/mmcblk0p2 rootwait
</code></pre>
<p>If you follow this from my <a target="_blank" href="https://blog.billvanleeuwen.ca/building-a-root-filesystem-for-the-beaglebone-black">earlier blog</a>, you might notice this is very similar to the commands we gave to U-Boot manually.</p>
<p>Finally, we need to unpack our root file system now to the second partition:</p>
<pre><code class="lang-bash">sudo tar -C /run/media/<span class="hljs-variable">$USER</span>/rootfs/ -xf rootfs.tar
</code></pre>
<p>Now our card is ready for the BeagleBone!</p>
<h2 id="heading-booting-our-system">Booting Our System</h2>
<p>With your serial adapter plugged into your PC, start up a <code>picocom</code> terminal:</p>
<pre><code class="lang-bash">picocom -b 115200 /dev/ttyUSB0
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676474991987/cb91b68f-5b20-4823-becd-a88210afd510.png" alt class="image--center mx-auto" /></p>
<p>Now, unmount the SD card's partitions, and insert the card into the board.</p>
<p>While plugging in the board, hold down the <code>USR</code> button to force the system to boot from the SD card.</p>
<p>You should see U-Boot and kernel output similar to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676475171867/eed6fe14-197f-437b-a790-2fee975aab3c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676475197042/046fd194-3586-4685-bf0f-5c35a856de0a.png" alt class="image--center mx-auto" /></p>
<p>Finally followed with the banner you set in the Buildroot menuconfig.</p>
<p>Login as root with the password you supplied:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676475310775/0c012a6a-1804-4141-a80e-992d7c1fc117.png" alt class="image--center mx-auto" /></p>
<p>And you've now installed a Buildroot Linux system on the board!</p>
<p>If you followed the optional steps in the config step, enjoy some ascii_invaders:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676475405933/791edd8c-b2ce-48a6-a9d0-31b5bc6f757f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676475410105/d1b6800f-16f7-4580-af77-3a199c65d28a.png" alt class="image--center mx-auto" /></p>
<p>This finishes the tutorial. Thanks for reading!</p>
]]></content:encoded></item><item><title><![CDATA[Building a Root Filesystem For the Beaglebone Black]]></title><description><![CDATA[This is Part 3 of this blog series, this is a continuation of the write-up for my assignment.
This blog is based on Bootlin's Embedded Linux Course as well as Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming, so you may have some...]]></description><link>https://blog.billvanleeuwen.ca/building-a-root-filesystem-for-the-beaglebone-black</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/building-a-root-filesystem-for-the-beaglebone-black</guid><category><![CDATA[embedded linux]]></category><category><![CDATA[beaglebone black]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Fri, 27 Jan 2023 14:46:54 GMT</pubDate><content:encoded><![CDATA[<p>This is Part 3 of this blog series, this is a continuation of the write-up for my assignment.</p>
<p>This blog is based on Bootlin's <a target="_blank" href="https://bootlin.com/training/embedded-linux/">Embedded Linux Course</a> as well as <a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming</a>, so you may have some success reading their materials alongside this blog.</p>
<p>In this section, we will finish our setup of a barebones Linux system for the Beaglebone Black. The Root Filesystem is the last essential piece of the Linux system. Ours will contain a familiar directory structure, as well as many of the basic programs you might be used to from a desktop Linux distribution.</p>
<h2 id="heading-creating-a-root-filesystem-from-scratch">Creating a Root Filesystem From Scratch</h2>
<p>The first step in this process is to create a staging directory in which to place the filesystem hierarchy for our future Beaglebones rootfs.</p>
<pre><code class="lang-bash">mkdir bin dev etc home lib proc sbin sys tmp usr var &amp;&amp; mkdir usr/bin usr/lib usr/sbin var/<span class="hljs-built_in">log</span>
</code></pre>
<p>Take a look at this structure with <code>tree -d</code>, which should now look like:</p>
<pre><code class="lang-plaintext">.
├── bin
├── dev
├── etc
├── home
├── lib
├── proc
├── sbin
├── sys
├── tmp
├── usr
│   ├── bin
│   ├── lib
│   └── sbin
└── var
    └── log
</code></pre>
<h2 id="heading-programs-needed-for-the-rootfs">Programs Needed for the rootfs</h2>
<p>According to <a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Mastering Embedded Linux Programming</a> - "Even for a basic root filesystem, you need approximately 50 utilities..." It goes on to mention that tracking down this source code for ourselves might be a true pain. (BusyBox)[https://busybox.net/] solves that problem for us. You can read more about BusyBox somewhere else, but all that is necessary to know here, is it provides us with the essential Linux utilities that we need, in a minimal package size.</p>
<p>Clone the git repo, and switch to a stable release with:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> git://busybox.net/busybox.git
<span class="hljs-built_in">cd</span> busybox
git checkout 1_35_0
</code></pre>
<p>Build the default configuration of BusyBox</p>
<pre><code class="lang-bash">make distclean
make defconfig
</code></pre>
<p>Export the toolchain and architecture like we did in (Part 3)[https://blog.billvanleeuwen.ca/compiling-and-porting-the-linux-kernel-to-the-beaglebone-black] of this blog series to avoid typing it in each <code>make</code> command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> ARCH=arm
<span class="hljs-built_in">export</span> CROSS_COMPILE=arm-training-linux-uclibcgnueabihf-
</code></pre>
<p>We want to install BusyBox in our staging directory. Enter the menu config with</p>
<pre><code class="lang-bash">make menuconfig
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675262259626/7803a1eb-50ff-40ee-8b35-e9eac81aa6f2.png" alt class="image--center mx-auto" /></p>
<p>Once in the menu, set the install path in <code>Settings -&gt; Destination path for 'make install'</code>. This should be the path for your rootfs directory we just created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675262274288/d1adc25c-cfd1-407c-961c-fe78780c6f20.png" alt class="image--center mx-auto" /></p>
<p>We also want busybox to statically compile. This will reduce complexity for us.</p>
<h3 id="heading-note-on-static-compilation">Note on Static Compilation</h3>
<p>You might not want to do this in most cases, as any further programs you install must also be statically compiled.</p>
<p>For the uninitiated <a target="_blank" href="https://www.usenix.org/legacy/publications/library/proceedings/jvm02/yu/yu_html/node3.html">Static Compilation</a> is the process of compiling all of the needed libraries together with the program itself, rather than using them externally. This saves complexity, as you don't need to worry about including extra object files in your rootfs, but the compromise is size. Many of these programs rely on the same libraries. You can imagine it would save on space if we didn't have to include these in each compiled program, and instead have a single object file for these to all dynamically link against. For our purposes (essentially building a toy Linux system nobody is ever going to use in production) this is fine.</p>
<p>Now run <code>make install</code> to build Busybox.</p>
<p>On following the instructions from bootlin and Mastering Embedded Linux, this step returned me an error:</p>
<pre><code class="lang-plaintext">networking/ping.c:158:11: fatal error: netinet/icmp6.h: No such file or directory
  158 | # include &lt;netinet/icmp6.h&gt;
</code></pre>
<p>I likely made a mistake in configuring my toolchain.</p>
<p>We dont need ipv6 for our limited scope project, so if this happens to you, it can be solved by disabling ipv6 support in the BusyBox menu config under Networking Utilities -&gt; Enable IPv6 Support</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675262639810/acf95081-24cc-46b3-b53e-1e8f830592ec.png" alt class="image--center mx-auto" /></p>
<p>Try ```tree`` in your staging directory to see what buysbox installed</p>
<pre><code class="lang-plaintext">.
├── bin
│   ├── arch -&gt; busybox
│   ├── ash -&gt; busybox
│   ├── base32 -&gt; busybox
│   ├── base64 -&gt; busybox
│   ├── busybox
│   ├── cat -&gt; busybox
│   ├── chattr -&gt; busybox
│   ├── chgrp -&gt; busybox
│   ├── chmod -&gt; busybox
│   ├── chown -&gt; busybox
│   ├── conspy -&gt; busybox
│   ├── cp -&gt; busybox

...

├── dev
├── etc
├── home
├── lib
├── linuxrc -&gt; bin/busybox
├── proc
├── sbin
│   ├── acpid -&gt; ../bin/busybox
│   ├── adjtimex -&gt; ../bin/busybox
│   ├── arp -&gt; ../bin/busybox
│   ├── blkid -&gt; ../bin/busybox
│   ├── blockdev -&gt; ../bin/busybox
│   ├── bootchartd -&gt; ../bin/busybox
│   ├── depmod -&gt; ../bin/busybox
│   ├── devmem -&gt; ../bin/busybox
│   ├── fbsplash -&gt; ../bin/busybox
│   ├── fdisk -&gt; ../bin/busybox
│   ├── findfs -&gt; ../bin/busybox

...

└── var
    └── log

16 directories, 397 files
</code></pre>
<p>Wow, look at all those programs! Imagine compiling and loading all of these yourself. Sheesh.</p>
<h2 id="heading-testing-our-system">Testing our system</h2>
<p>You should have two partitions on your SD card that we created in (part 2)[https://blog.billvanleeuwen.ca/porting-u-boot-onto-the-beaglebone] of this series.</p>
<p>Insert your SD card into the PC, and copy all of the files and folders from your staging directory to the rootfs partition on your SD card.</p>
<p>Eject the card, and slot it into your Beaglebone.</p>
<p>Like before, hold the USR button as you power up the Beaglebone, and spam the spacebar in the picocom terminal.</p>
<p>You should see the u-boot command line: <code>=&gt;</code></p>
<p>You should still have the <code>bootcmd</code> environment variable defined. We need to set another so that we can mount our rootfs and avoid the kernel panic from earlier.</p>
<pre><code class="lang-plaintext">setenv bootargs console=ttyO0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait init=/bin/sh +m
</code></pre>
<p>This tells the system that we have our root filesystem on the second partition of our SD card.</p>
<p>Go ahead and reboot the system with <code>boot</code>.</p>
<p>You should now avoid the kernel panic, and see something like this in your console:</p>
<pre><code class="lang-plaintext">[    2.266649] VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
[    2.274829] devtmpfs: mounted
[    2.279609] Freeing unused kernel image (initmem) memory: 1024K
[    2.288104] Run /sbin/init as init process
[    2.304033] mmc1: new high speed MMC card at address 0001
[    2.311922] mmcblk1: mmc1:0001 M62704 3.56 GiB 
[    2.319848]  mmcblk1: p1
[    2.323613] mmcblk1boot0: mmc1:0001 M62704 2.00 MiB 
[    2.335241] mmcblk1boot1: mmc1:0001 M62704 2.00 MiB 
[    2.350386] mmcblk1rpmb: mmc1:0001 M62704 512 KiB, chardev (250:0)
[    4.887550] random: crng init done
can't run '/etc/init.d/rcS': No such file or directory

Please press Enter to activate this console.
</code></pre>
<p>Great! Hit enter, and you now have a rather minimal Linux system running!</p>
<pre><code class="lang-bash">/ <span class="hljs-comment"># ls</span>
bin      etc      lib      proc     sys      usr
dev      home     linuxrc  sbin     tmp      var
/ <span class="hljs-comment"># cd bin/</span>
/bin <span class="hljs-comment"># ls</span>
arch           dumpkmap       <span class="hljs-built_in">kill</span>           netstat        setserial
ash            <span class="hljs-built_in">echo</span>           link           nice           sh
base32         ed             linux32        pidof          sleep
base64         egrep          linux64        ping           <span class="hljs-built_in">stat</span>
busybox        <span class="hljs-literal">false</span>          ln             pipe_progress  stty
cat            fatattr        login          printenv       su
chattr         fdflush        ls             ps             sync
chgrp          fgrep          lsattr         <span class="hljs-built_in">pwd</span>            tar
chmod          fsync          lzop           reformime      touch
chown          getopt         makemime       resume         <span class="hljs-literal">true</span>
conspy         grep           mkdir          rev            umount
cp             gunzip         mknod          rm             uname
cpio           gzip           mktemp         rmdir          usleep
cttyhack       hostname       more           rpm            vi
date           hush           mount          run-parts      watch
dd             ionice         mountpoint     scriptreplay   zcat
df             iostat         mpstat         sed
dmesg          ipcalc         mt             setarch
dnsdomainname  kbd_mode       mv             setpriv
/bin <span class="hljs-comment">#</span>
</code></pre>
<p>There is however an error from the kernel:</p>
<pre><code class="lang-plaintext">can't run '/etc/init.d/rcS': No such file or directory
</code></pre>
<p>/etc/init.d/rcS is supposed to be an init script called by busybox's init system. This needs to be defined by us, which we will do in the next step.</p>
<h2 id="heading-the-init-system">The Init system</h2>
<p>Back in our staging directory, create two files.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> etc
mkdir init.d
touch init.d/rcS
touch inittab
</code></pre>
<p>Copy the sample inittab file from (bootlins example)[https://elixir.bootlin.com/busybox/1.35.0/source/examples/inittab] into your inittab file</p>
<p>Because we aren't doing anything serious with our system. <code>init.d/rCs</code> can be left empty. Normally you could define any extra init scripts or commands in this file.</p>
<p>Copy these files over to your rootfs directory. Start up your Beaglebone by the method before and viola! The error should be gone!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've now successfully ported a minimal Linux system onto the Beaglebone!</p>
<p>You could take this one step further and flash it onto the onboard eMMC, but for the sake of this blog series, I won't go into that here.</p>
]]></content:encoded></item><item><title><![CDATA[Compiling and Porting the Linux Kernel to the Beaglebone Black]]></title><description><![CDATA[This is Part 3 of this blog series, this is a continuation of the write-up for my assignment.
This blog is based on Bootlin's Embedded Linux Course as well as Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming, so you may have some...]]></description><link>https://blog.billvanleeuwen.ca/compiling-and-porting-the-linux-kernel-to-the-beaglebone-black</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/compiling-and-porting-the-linux-kernel-to-the-beaglebone-black</guid><category><![CDATA[embedded linux]]></category><category><![CDATA[beaglebone black]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Tue, 24 Jan 2023 02:05:40 GMT</pubDate><content:encoded><![CDATA[<p>This is Part 3 of this blog series, this is a continuation of the write-up for my assignment.</p>
<p>This blog is based on Bootlin's <a target="_blank" href="https://bootlin.com/training/embedded-linux/">Embedded Linux Course</a> as well as <a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming</a>, so you may have some success reading their materials alongside this blog.</p>
<p>In this section, we will be compiling, and configuring the Linux kernel and porting it to the Beaglebone Black.</p>
<p>If you haven't read <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-cross-compiling-toolchain-for-beaglebone-black-with-crosstool-ng">Part 1</a> and <a target="_blank" href="https://blog.billvanleeuwen.ca/porting-u-boot-onto-the-beaglebone">Part 2</a> of this series, you may be lost.</p>
<h2 id="heading-fetching-the-source-code">Fetching the source code</h2>
<p>First, clone the Linux repository into an appropriate directory.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
</code></pre>
<p>This repository is, at the time of writing, 2.5GB, so go grab a coffee.</p>
<p>Now we have the Linux source code on our machine. However, these are the 'mainline' releases where we would be best off using the 'stable' releases. These are maintained in a separate repository. For more info on what this means, check out <a target="_blank" href="https://www.kernel.org/category/releases.html">This Page</a> on the differences.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> linux
git remote add stable https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux
git fetch stable
</code></pre>
<p>This again may take a while depending on your internet speed.</p>
<h2 id="heading-cross-compiling-the-kernel">Cross-compiling the kernel</h2>
<p>At the time of writing, <code>remotes/stable/linux-6.1.y</code> is the latest stable release, you can check your branches with</p>
<pre><code class="lang-bash">git branch -a
</code></pre>
<p>You can check which kernel version the local repository is on with</p>
<pre><code class="lang-bash">make kernel version
</code></pre>
<p>My output was: <code>6.2.0-rc5</code></p>
<p><em>Aside</em> - This means <a target="_blank" href="https://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a> is currently working on releasing Linux 6.2.0, and on Release Candidate #5. Again, check <a target="_blank" href="https://www.kernel.org/category/releases.html">This Page</a> to learn more about what that means.</p>
<p>Let's choose the newest stable branch in an attempt to stay current.</p>
<pre><code class="lang-bash">git checkout remotes/stable/linux-6.1.y
</code></pre>
<p>Try <code>make kernelversion</code> again to see the difference.</p>
<p>Define some environment variables so Linux's make scripts know what we want to compile for an ARM board, and know what C compiler we want to use (make sure the cross-compiling toolchain we made in <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-cross-compiling-toolchain-for-beaglebone-black-with-crosstool-ng">Part 1</a> of this blog series is on the PATH).</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> ARCH=arm
<span class="hljs-built_in">export</span> CROSS_COMPILE=arm-training-linux-uclibcgnueabihf-
</code></pre>
<p>Run <code>make help</code>. Without exporting the variables above, or including them in the command, your output will look much different. This will show you all of the configurations Linux can build for. Ours for the Beaglebone is multi_v7_defconfig (<a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming</a> says to use this one, while <a target="_blank" href="https://bootlin.com/training/embedded-linux/">Bootlin</a> says to use omap2plus_defconfig, but both worked for me.)</p>
<p>Enter the configuration menu with <code>make menuconfig</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674525847163/2244d75c-a96e-412b-be97-7be8d99db6cc.png" alt class="image--center mx-auto" /></p>
<p>In this menu, find and disable CONFIG_GCC_PLUGINS. Bootlin suggests this, as it will skip building special plugins which require extra dependencies, and we don't need them. You can find the location of this using typical vim commands. Enter <code>/</code> to search for this option.</p>
<p>Now, we're ready to compile the kernel!</p>
<pre><code class="lang-bash"><span class="hljs-comment"># replace &lt;n&gt; with the amount of cores your CPU has to parallelize the build</span>
make zImage -j&lt;n&gt;
</code></pre>
<p>Now sit back and wait for a bit. This will take a while depending on your CPU speed and core count.</p>
<p>Once the kernel compiles, you'll need to find two files and copy them to the <code>boot</code> partition of the SD card.</p>
<pre><code class="lang-plaintext">arch/arm/boot/zImage
arch/arm/boot/dts/am335x-boneblack.dtb
</code></pre>
<p>These are the kernel image, and the device tree file respectively.</p>
<p>Congratulations! You've compiled the kernel from source!</p>
<h2 id="heading-booting-the-kernel">Booting the Kernel</h2>
<p>Plug in your USB to TTL cable, and start-up picocom to get a serial connection to the Beaglebone.</p>
<pre><code class="lang-bash">picocom -b 115200 /dev/ttyUSB0
</code></pre>
<p>We still want to boot from the SD card, rather than the bootloader on the eMMC. Be ready to press the space bar on your keyboard to avoid going through U-Boot's auto-boot sequence. Hold down the USR button, and plug in the cord to provide power to the Beaglebone.</p>
<p>Be sure you're greeted by your bootloader rather than the one on the eMMC. Check the date, like from <a target="_blank" href="https://blog.billvanleeuwen.ca/porting-u-boot-onto-the-beaglebone">Part 2</a> of this series, and make sure it's the date in which you compiled U-Boot.</p>
<p>You should see the familiar prompt =&gt; on your picocom terminal.</p>
<p>Once the kernel boots up, we want it to send its output to its UART pins, which are the ones our USB to TTL converter are connected. Enter the following into your picocom terminal.</p>
<pre><code class="lang-bash">=&gt; setenv bootargs console=ttyS0,115200n8
=&gt; saveenv
</code></pre>
<p>Now we're going to load the kernel image, and device tree file into memory:</p>
<pre><code class="lang-bash">=&gt; fatload mmc 0:1 0x80200000 zImage
=&gt; fatload mmc 0:1 0x80f00000 am335x-boneblack.dtb
</code></pre>
<p>Let's boot this sucker!</p>
<pre><code class="lang-bash">=&gt; bootz 0x80200000 - 0x80f00000
</code></pre>
<p>What you'll see in the output might look similar to:</p>
<pre><code class="lang-plaintext">[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 6.1.7 (billsDesktop@fedora) (arm-linux-gcc (crosstool-NG 1.25.0.95_7622b49) 11.3.0, GNU ld (crosstool-NG 1.25.0.95_7622b49) 2.39) #2 SMP Mon Jan 23 20:25:30 EST 2023
[    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt: Machine model: TI AM335x BeagleBone Black

...

[    3.472852] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    3.481165] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.1.7 #2
[    3.487037] Hardware name: Generic AM33XX (Flattened Device Tree)
[    3.493177]  unwind_backtrace from show_stack+0x10/0x14
[    3.498478]  show_stack from dump_stack_lvl+0x40/0x4c
[    3.503584]  dump_stack_lvl from panic+0x108/0x33c
[    3.508434]  panic from mount_block_root+0x168/0x208
[    3.513462]  mount_block_root from prepare_namespace+0x150/0x18c
[    3.519523]  prepare_namespace from kernel_init+0x18/0x12c
[    3.525061]  kernel_init from ret_from_fork+0x14/0x2c
[    3.530156] Exception stack(0xe0009fb0 to 0xe0009ff8)
[    3.535240] 9fa0:                                     00000000 00000000 00000000 00000000
[    3.543464] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    3.551684] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[    3.558350] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
</code></pre>
<p>This last section might be problematic for someone not in our shoes, but for us, this <a target="_blank" href="https://www.makeuseof.com/tag/dont-panic-everything-you-need-to-know-about-kernel-panics/">Kernel Panic</a> is mentioning that we don't have a root file system mounted. That's OK, we'll get to that in the next blog series.</p>
<p>For now, let's be happy we've booted a cross-compiled Linux kernel on the Beaglebone!</p>
<p>Automate this process with a simple bootscript:</p>
<pre><code class="lang-bash">=&gt; setenv bootcmd <span class="hljs-string">'fatload mmc 0:1 0x80200000 zImage; fatload mmc 0:1 0x80f00000 am335x-boneblack.dtb; bootz 0x80200000 - 0x80f00000'</span>
=&gt; saveenv
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Porting U-Boot onto the Beaglebone]]></title><description><![CDATA[Similar to Part 1 of this blog series, this is a continuation of the write-up for my assignment.
This blog is based on Bootlin's Embedded Linux Course as well as Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming, so you may have s...]]></description><link>https://blog.billvanleeuwen.ca/porting-u-boot-onto-the-beaglebone</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/porting-u-boot-onto-the-beaglebone</guid><category><![CDATA[beaglebone black]]></category><category><![CDATA[bootloader]]></category><category><![CDATA[embedded linux]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Sun, 22 Jan 2023 06:28:16 GMT</pubDate><content:encoded><![CDATA[<p>Similar to <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-cross-compiling-toolchain-for-beaglebone-black-with-crosstool-ng">Part 1</a> of this blog series, this is a continuation of the write-up for my assignment.</p>
<p>This blog is based on Bootlin's <a target="_blank" href="https://bootlin.com/training/embedded-linux/">Embedded Linux Course</a> as well as <a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming</a>, so you may have some success reading their materials alongside this blog.</p>
<p>We now have to install the bootloader <a target="_blank" href="https://github.com/u-boot/u-boot">U-Boot (Das U-Boot is the full name)</a> onto the board.</p>
<p>If you are not familiar, the bootloader is a piece of software that often runs first, or close to first on the hardware (dependent on the board architecture and some other things).</p>
<p>From <a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming</a>:</p>
<pre><code class="lang-plaintext">In an embedded Linux system, the bootloader has two main jobs: to initialize the system
to a basic level and to load the kernel. In fact, the first job is somewhat subsidiary to the
second, in that it is only necessary to get as much of the system working as is needed to
load the kernel.
</code></pre>
<h2 id="heading-connect-your-serial-adapter-to-the-board">Connect your serial adapter to the board</h2>
<p>We need access to the Beaglebone, and the only way to do this once we load the bootloader is through the serial port.</p>
<p>Your serial adapter's colours may vary. So you may need to look up the spec for your cable. I'm using this <a target="_blank" href="https://www.dtechelectronics.com/dtech-ftdi-usb-to-ttl-serial-3-3v-adapter-cable-ft232rl-chip-6ft-1-8m-black-tx-rx-signal-4-pin-0-1-inch-pitch-female-socket-windows-10-8-7-xp-vista_p319.html">Dtech USB to TTL cable</a> I bought for $15 CAD on <a target="_blank" href="https://www.amazon.ca/dp/B08G1JTN4N?psc=1&amp;ref=ppx_yo2ov_dt_b_product_details">Amazon</a>. You can likely find one cheaper direct from China if you're willing to wait for shipping.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674368646328/693ff41d-8819-4198-9a94-e51ff5337eae.jpeg" alt class="image--center mx-auto" /></p>
<p><strong><em>2025, Sept - Edit:</em></strong> <em>I’m looking back through these blogs to replicate this previous work. I’ve realised the photo here is incorrect. The TXD and RXD are swapped.</em></p>
<p>The pins are labelled 1-6 from right to left (in the perspective of this image). Pin 1 is ground, <s>4 and 5 are the boards Rx, and Tx respectively </s> Pin 4 is the TXD and 5 is the RXD. Tx is SEND and Rx is RECIEVE, so you need to reverse this order for your cable such that the cables Tx is plugged into the boards Rx, and vice versa.</p>
<p>To communicate with the board, you will need a serial communication program. <a target="_blank" href="https://github.com/npat-efault/picocom">picocom</a> is a good and minimal choice for our use. In order to get access to the serial port, you need to add yourself to the dialout group.</p>
<pre><code class="lang-bash">sudo dnf install picocom
sudo usermod -a -G dialout <span class="hljs-variable">$USER</span>
</code></pre>
<p>You will need to reboot for the dialout change to take affect. You CAN access <code>/dev/ttyUSB0/</code> as root, or with <code>sudo</code> but you SHOULD NOT run things as root unless you have to, with the risk of ruining your system.</p>
<h2 id="heading-cross-compiling-u-boot">Cross-compiling U-Boot</h2>
<p>You should have your cross-compiler set up from <a target="_blank" href="https://blog.billvanleeuwen.ca/creating-a-cross-compiling-toolchain-for-beaglebone-black-with-crosstool-ng">Part 1</a> of this series. If not, you wont be able to continue from here on out.</p>
<p>Check out the U-Boot source code from <a target="_blank" href="https://source.denx.de/u-boot/u-boot/-/commits/master?search=v2">gitlab</a> (the <a target="_blank" href="https://github.com/u-boot/u-boot">github</a> version is an identical mirror, and will work just fine if that's your preference).</p>
<p>Bootlin releases the source code as commits in its git repository. Clone the source and check out the latest release with:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://source.denx.de/u-boot/u-boot.git
<span class="hljs-built_in">cd</span> u-boot
git checkout v2023.01
</code></pre>
<p>To understand the compilation steps further than this tutorial for u-boot, see the README.</p>
<p>Since we are cross-compiling:</p>
<blockquote>
<p>If you are not using a native environment, it is assumed that you have GNU cross compiling tools available in your path. In this case, you must set the environment variable CROSS_COMPILE in your shell. Note that no changes to the Makefile or any other source files are necessary. For example using the ELDK on a 4xx CPU, please enter:</p>
<pre><code class="lang-bash">    $ CROSS_COMPILE=ppc_4xx-
    $ <span class="hljs-built_in">export</span> CROSS_COMPILE
</code></pre>
</blockquote>
<p>We can shorten this to a simple one-liner with:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> CROSS_COMPILE=arm-linux-
</code></pre>
<blockquote>
<p>U-Boot is intended to be simple to build. After installing the sources you must configure U-Boot for one specific board type. This is done by typing:</p>
<p><code>make NAME_defconfig</code></p>
<p>where "NAME_defconfig" is the name of one of the existing configu- rations; see configs/*_defconfig for supported names</p>
</blockquote>
<p>To configure U-Boot for our board:</p>
<pre><code class="lang-bash">make am335x_evm_defconfig .
</code></pre>
<p>Now, depending whether you have the wired or wireless beaglebone, run:</p>
<pre><code class="lang-bash">make DEVICE_TREE=am335x-boneblack
</code></pre>
<p>or</p>
<pre><code class="lang-bash">make DEVICE_TREE=am335x-boneblack-wireless
</code></pre>
<p>You are now building U-Boot!</p>
<p>From bootlin:</p>
<blockquote>
<p>The DEVICE_TREE variable specifies the specific Device Tree that describes our hardware board.</p>
</blockquote>
<h2 id="heading-prepping-the-sd-card">Prepping the SD Card</h2>
<p>From bootlin:</p>
<blockquote>
<p>The TI romcode will look for an MLO (MMC Load) file in a FAT partition on an SD card. This is precisely what U-Boot compiled for us, together with the U-Boot binary (u-boot.img).</p>
</blockquote>
<p>Insert the SD card into your PC. I don't have a port for one, so I'm using a USB adapter. Find the SD card 'device filename':</p>
<pre><code class="lang-bash">dmesg
</code></pre>
<p>your output will look something like:</p>
<pre><code class="lang-plaintext">[10600.641343] usb 2-3: new SuperSpeed USB device number 4 using xhci_hcd
[10600.661566] usb 2-3: New USB device found, idVendor=8564, idProduct=4000, bcdDevice= 0.38
[10600.661574] usb 2-3: New USB device strings: Mfr=3, Product=4, SerialNumber=5
[10600.661578] usb 2-3: Product: Transcend
[10600.661581] usb 2-3: Manufacturer: TS-RDF5 
[10600.661584] usb 2-3: SerialNumber: 000000000037
[10600.668454] usb-storage 2-3:1.0: USB Mass Storage device detected
[10600.669577] scsi host9: usb-storage 2-3:1.0
[10601.697428] scsi 9:0:0:0: Direct-Access     TS-RDF5  SD  Transcend    TS38 PQ: 0 ANSI: 6
[10601.697881] sd 9:0:0:0: Attached scsi generic sg0 type 0
[10602.090927] sd 9:0:0:0: [sda] 124735488 512-byte logical blocks: (63.9 GB/59.5 GiB)
[10602.092385] sd 9:0:0:0: [sda] Write Protect is off
[10602.092391] sd 9:0:0:0: [sda] Mode Sense: 23 00 00 00
[10602.093987] sd 9:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[10602.102665]  sda: sda1
[10602.102917] sd 9:0:0:0: [sda] Attached SCSI removable disk
</code></pre>
<p>What we can gain from this output, is that we have a SCSI disk attached. (If you're unfamiliar, <a target="_blank" href="https://en.wikipedia.org/wiki/SCSI">SCSI</a> is both an older physical interface, and a communication standard for disks. Though we have attached an SD card, Linux will always see it as a SCSI disk).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674368759043/9c2fbfb7-5d1b-4ba8-81e9-9d27fde6de9c.jpeg" alt class="image--center mx-auto" /></p>
<p>This line <code>[10602.102665] sda: sda1</code> shows that this disk is named <code>sda1</code>, or 'SCSI Disk A 1'. This lives in <code>/dev/sda1</code>.</p>
<p>We need to unmount any partitions of this SD card before modifying its partition table. Check if any are mounted with:</p>
<pre><code class="lang-bash">sudo mount | grep sda1
</code></pre>
<p>which might output:</p>
<pre><code class="lang-plaintext">/dev/sda1 on /run/media/billsDesktop/16E3-7820 type exfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,iocharset=utf8,errors=remount-ro,uhelper=udisks2)
</code></pre>
<p>If this, or any others are mounted, unmount them with</p>
<pre><code class="lang-bash">sudo umount /dev/sda1*
</code></pre>
<p>Manually erase the partition table on this card with:</p>
<pre><code class="lang-bash">sudo dd <span class="hljs-keyword">if</span>=/dev/zero of=/dev/sda1 bs=1M count=16
</code></pre>
<p>Note: My post deviates from bootlin's material here. I found their method didn't work for me. This method is from <a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming</a>. The authours have a script to do this as well on <a target="_blank" href="https://github.com/PacktPublishing/Mastering-Embedded-Linux-Programming-Third-Edition">the book's github page</a></p>
<p>Create two partitions on the card with:</p>
<pre><code class="lang-bash">sudo sfdisk /dev/<span class="hljs-variable">${DRIVE}</span> &lt;&lt; EOF
,64M,0x0c,*
,1024M,L,
EOF
</code></pre>
<p>What we did here was manually add a partition table to the card. One 64MB, FAT32, bootable partition, and another 1GB ext4.</p>
<p>We only need the one for now, but once we mount a root filesystem in a later blog, it will be useful that we've already done it.</p>
<p>Create FAT16 and ext4 filesystems on this partition with:</p>
<pre><code class="lang-bash">sudo mkfs.vfat -a -F 16 -n boot /dev/sda1p1
sudo mkfs.ext4 -L rootfs /dev/sda1p2
</code></pre>
<p>This should mount to your PC automatically. If not, remove and reinsert the SD card.</p>
<p>What we've done above might also be possible using a GUI tool like <a target="_blank" href="https://gparted.org/">GParted</a></p>
<p>Now we that have a bootable partition on the card, go ahead and copy the compiled U-Boot image onto the card.</p>
<p>The directory for the SD card may be dependent on your workstations distribution, and whether you are using a USB adapter or inserting it directly into the PC. You should also just be able to drag and drop the files in the file explorer.</p>
<pre><code class="lang-bash">cp MLO u-boot.img /run/media/<span class="hljs-variable">$USER</span>/boot/
</code></pre>
<h2 id="heading-testing-u-boot">Testing U-Boot</h2>
<p>Make sure your USB to Serial connector is plugged into the board and your PC from earlier.</p>
<p>Start monitoring the serial port with:</p>
<pre><code class="lang-bash">picocom -b 115200 /dev/ttyUSB0
<span class="hljs-comment">#-b is setting the baud rate for the asynchronous serial connection</span>
</code></pre>
<p>Insert the SD card into the beaglebone with no power going to it. Hold down the small black button next to the SD card, plug in the power cable, and let go of the button after a few seconds.</p>
<p>Your output should start with something like this:</p>
<pre><code class="lang-plaintext">U-Boot SPL 2023.01 (Jan 21 2023 - 23:09:14 -0500)
Trying to boot from MMC1


U-Boot 2023.01 (Jan 21 2023 - 23:09:14 -0500)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM:  512 MiB
Core:  160 devices, 18 uclasses, devicetree: separate
WDT:   Started wdt@44e35000 with servicing every 1000ms (60s timeout)
NAND:  0 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... 
&lt;ethaddr&gt; not set. Validating first E-fuse MAC
Net:   eth2: ethernet@4a100000, eth3: usb_ether
Hit any key to stop autoboot:  0 
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
No EFI system partition
BootOrder not defined
EFI boot manager: Cannot load any image
switch to partitions #0, OK
mmc1(part 0) is current device
Scanning mmc 1:1...
BootOrder not defined
EFI boot manager: Cannot load any image
## Error: "bootcmd_nand0" not defined

...
</code></pre>
<p>Make sure the date and time are correct for when you compiled U-Boot. Otherwise, the beaglebone is booting the preloaded U-Boot from its internal eMMC. If it's off, you've done something wrong.</p>
<p>The output will be followed by:</p>
<pre><code class="lang-plaintext">=&gt;
</code></pre>
<p>Which is the U-Boot command line! SUCCESS! You are officially running your own cross-compiled bootloader.</p>
<h2 id="heading-playing-with-u-boot">Playing With U-Boot</h2>
<p>We have completed this blog section, but in case you were more curious about U-Boot, enter <code>help</code> to see the commands available to U-Boot :)</p>
]]></content:encoded></item><item><title><![CDATA[Creating a Cross-compiling Toolchain For Beaglebone Black With Crosstool-NG]]></title><description><![CDATA[This semester, I am doing an independent study course on embedded Linux. This tutorial is the writeup for part 1 of my first assignment
This blog is based on Bootlin's Embedded Linux Course as well as Frank Vasquez and Chris Simmonds Mastering Embedd...]]></description><link>https://blog.billvanleeuwen.ca/creating-a-cross-compiling-toolchain-for-beaglebone-black-with-crosstool-ng</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/creating-a-cross-compiling-toolchain-for-beaglebone-black-with-crosstool-ng</guid><category><![CDATA[embedded linux]]></category><category><![CDATA[ARM]]></category><category><![CDATA[beaglebone black]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Wed, 18 Jan 2023 02:50:46 GMT</pubDate><content:encoded><![CDATA[<p>This semester, I am doing an independent study course on embedded Linux. This tutorial is the writeup for part 1 of my first assignment</p>
<p>This blog is based on Bootlin's <a target="_blank" href="https://bootlin.com/training/embedded-linux/">Embedded Linux Course</a> as well as <a target="_blank" href="https://www.packtpub.com/product/mastering-embedded-linux-programming-third-edition/9781789530384">Frank Vasquez and Chris Simmonds Mastering Embedded Linux Programming</a>, so you may have some success reading their materials alongside this blog.</p>
<h2 id="heading-the-toolchain-generator">The Toolchain Generator</h2>
<p><a target="_blank" href="https://crosstool-ng.github.io/">Crosstool-ng</a> is a cross-compiling toolchain generator.</p>
<p>For those that don't know, a cross-compiling toolchain is not much different from a general toolchain you might use in regular C/C++ development (for example <code>gcc</code> or <code>g++</code>). However, the cross-compiler generates binaries for other architectures, in this case, ARM.</p>
<p>Our toolchain needs to have some special setup though. To write code to interface with the kernel, we need the Linux kernel headers. Therefore, our toolchain needs to insert these headers, as well as a specific C library.</p>
<p>We're going to use <a target="_blank" href="https://uclibc-ng.org/">uClibc</a> for our project. uClibc is a very small C library designed for embedded applications. It has a focus on small size over performance.</p>
<h2 id="heading-compiling-crosstool-ng">Compiling crosstool-NG</h2>
<p>I am semi-following the instructions from <a target="_blank" href="https://crosstool-ng.github.io/docs/install/">the crosstool-NG documentation</a></p>
<p>First, clone the git repository.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/crosstool-ng/crosstool-ng
<span class="hljs-built_in">cd</span> crosstool-ng/
</code></pre>
<p>Next, we need to configure and build the source code. There are two ways to do this, however, I'll be following the <em>hacker's way</em> which allows us to run this locally, rather than exporting it to the PATH.</p>
<pre><code class="lang-bash">./bootstrap
./configure --enable-local
</code></pre>
<p>Likely you will need to run this configure script multiple times, installing missing packages along the way. If you're not on Ubuntu like me, you might need to do some tactical googling along the way to discover the alternate package names.</p>
<p>after fiddling, you can compile.</p>
<pre><code class="lang-bash">make
</code></pre>
<h2 id="heading-creating-the-toolchain">Creating the toolchain</h2>
<p>you can see the help menu by entering:</p>
<pre><code class="lang-bash">./ct-ng <span class="hljs-built_in">help</span>
</code></pre>
<p>we want to use the cortex a8 sample since that will remove much of the configuring we might need to do. you can see all the samples with:</p>
<pre><code class="lang-bash">./ct-ng list-samples
</code></pre>
<p>we like the a8 one, so:</p>
<pre><code class="lang-bash">./ct-ng arm-cortex_a8-linux-gnueabi
</code></pre>
<p>ok, now let's enter the menu and configure our toolchain</p>
<pre><code class="lang-bash">./ct-ng menuconfig
</code></pre>
<p>the menu should look something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674010050239/0e95d298-2552-436c-b0c2-2d6108da75cf.png" alt="crosstool menu" class="image--center mx-auto" /></p>
<p>Configure the toolchain as follows (excerpt from <code>embedded-linux-bbb-labs.pdf</code>):</p>
<blockquote>
<p><strong>In Path and misc options:</strong></p>
<p>• Change Maximum log level to see to DEBUG (look for LOG_DEBUG in the interface, using the / key) so that we can have more details on what happened during the build in case something went wrong.</p>
<p><strong>In Target options:</strong></p>
<p>• Set Use specific FPU (ARCH_FPU) to vfpv3.</p>
<p>• Set Floating point to hardware (FPU).</p>
<p><strong>In Toolchain options:</strong></p>
<p>• Set Tuple's vendor string (TARGET_VENDOR) to training.</p>
<p>• Set Tuple's alias (TARGET_ALIAS) to arm-linux. This way, we will be able to use the compiler as arm-linux-gcc instead of arm-training-linux-uclibcgnueabihf-gcc, which is much longer to type.</p>
<p><strong>In Operating System:</strong></p>
<p>• Set Version of linux to the 5.15.x version that is proposed. We choose this version because this matches the version of the kernel we will run on the board. At least, the version of the kernel headers are not more recent.</p>
<p><strong>In C-library:</strong></p>
<p>• If not set yet, set C library to uClibc-ng (LIBC_UCLIBC_NG)</p>
<p>• Keep the default version that is proposed</p>
<p>• If needed, enable Add support for IPv6 (LIBC_UCLIBC_IPV6)2 , Add support for WCHAR (LIBC_UCLIBC_WCHAR) and Support stack smashing protection (SSP) (LIBC_UCLIBC_HAS_ SSP)</p>
<p><strong>In C compiler:</strong></p>
<p>• Set Version of gcc to 11.3.0. We need to stick to gcc 11.x, as Buildroot 2022.02 which we are going to use later doesn’t support gcc 12.x toolchains yet: gcc 12.x was released after Buildroot 2022.02.</p>
<p>• Make sure that C++ (CC_LANG_CXX) is enabled</p>
<p><strong>In Debug facilities:</strong></p>
<p>• Disable duma, gdb, ltrace. They will not be needed for the labs that will use this toolchain.</p>
<p>• Keep only strace (DEBUG_STRACE) enabled</p>
</blockquote>
<p>now, we are ready to build the toolchain:</p>
<pre><code class="lang-bash">./ct-ng build
</code></pre>
<p>this may take a while, as we're building an entire arm compiler, linker, debugger, etc.</p>
<p>Now that it's built, you should add <code>$HOME/x-tools/arm-training-linux-uclibcgnueabihf/bin</code> to your PATH. My perfered way of doing this is modifying your <code>~/.profile</code> file which should define your PATH.</p>
<h2 id="heading-confirm-that-the-toolchain-works">Confirm that the toolchain works.</h2>
<p>take this ultra-simple C file:</p>
<pre><code class="lang-C"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdlib.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span> <span class="hljs-params">(<span class="hljs-keyword">void</span>)</span>
</span>{
    <span class="hljs-built_in">printf</span>( <span class="hljs-string">"Hello world!\n"</span> );
    <span class="hljs-keyword">return</span> EXIT_SUCCESS;
}
</code></pre>
<p>Create a <code>hello.c</code> file, and put this as the contents.</p>
<p>try compiling with <code>arm-linux-gcc -o hello hello.c</code></p>
<p>if you receive bash: <code>arm-linux-gcc: command not found...</code> you haven't added the compiler to your PATH properly.</p>
<p>otherwise, you should now see your compiled C file. Typically, you would run this file with <code>./hello</code>, but you will receive <code>bash: ./hello: cannot execute binary file: Exec format error</code>. This is because we've now compiled this binary to ARM rather than X86, which is what we wanted!! :)</p>
<p>In order to test this, we'll need an arm VM. <a target="_blank" href="https://www.qemu.org/">qemu</a> is the obvious choice here. Go ahead and install it with <code>sudo dnf install qemu-user</code> if you are a fellow RHEL/Fedora user like yours truly. <code>sudo apt install qemu-user</code> will work if you use Ubuntu or a Debian-based distro.</p>
<p>Try running the binary with <code>qemu-arm hello</code>.</p>
<p>You will receive the error <code>/lib/ld-uClibc.so.0: No such file or directory</code>. This is because qemu is missing our C library, uClibc. This was compiled into an object file by our configuration with crosstool-NG. Tell qemu where to find it with <code>qemu-arm -L ~/x-tools/arm-training-linux-uclibcgnueabihf/arm-training-linux-uclibcgnueabihf/sysroot hello</code></p>
<p>You should now see the classic: <code>Hello world!</code></p>
<p>Congratulations! You've compiled your first ARM program with a toolchain you've created yourself!</p>
]]></content:encoded></item><item><title><![CDATA[First Hackathon. TOHacks 2022]]></title><description><![CDATA[My friends Lindsay, Avery and I decided to join this Hackathon!
We weren't there to win, just to learn along the way.
We were excited mainly to to see what we could do as a team.
We decided to build a simple app that would take a users email address,...]]></description><link>https://blog.billvanleeuwen.ca/first-hackathon-tohacks-2022</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/first-hackathon-tohacks-2022</guid><category><![CDATA[hackathon]]></category><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Sat, 28 May 2022 17:13:47 GMT</pubDate><content:encoded><![CDATA[<p>My friends Lindsay, Avery and I decided to join this Hackathon!
We weren't there to win, just to learn along the way.</p>
<p>We were excited mainly to to see what we could do as a team.</p>
<p>We decided to build a simple app that would take a users email address, and then on each email submitted, we would plant one tree.</p>
<h2 id="heading-problems-to-solve-along-the-way">Problems to solve along the way</h2>
<h3 id="heading-setting-up-the-webserver">Setting up the webserver</h3>
<p>As much as this was a problem, I love System Operations. I enjoyed setting up the Linux machine, web server, database, and dev environment. There were a few hiccups (mostly problems I created myself), like permissions errors, github authentication setup. But these errors really just contributed to my education on this topic.</p>
<h3 id="heading-the-api">The API</h3>
<p>I know what a REST API is, I understand it, but I had seldom used them. </p>
<p>We were calling the API using PHP, which was something I had to learn how to do. I struggled figuring this out, I kept getting errors. Eventually only to figure out that i spelled the URL wrong! Rookie mistake.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Overall, had a great time at the hackathon with my friends. Very mentally draining, but I'm super happy I experienced it.</p>
<h2 id="heading-my-contributions">My Contributions</h2>
<ul>
<li>Set up LAMP server with one click linode marketplace</li>
<li>Linux admin:<ul>
<li>created new accounts for my teamates</li>
<li>symlinked folders for their dev purposes</li>
<li>Setup mysql users</li>
<li>fixed user problems</li>
</ul>
</li>
<li>Setting up mysql</li>
<li>Had to add 2gb of swap space because PHP composer uses a load of ram</li>
<li>Utilized the REST API, reading documentation, formatting request, etc</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Writing an HTTP Server in C]]></title><description><![CDATA[One project I've really been keen to work on for a year or so now has been an HTTP server.
I'm not exactly sure why this interested me, but it might have something to do with my facination for critical infrastructure. Http servers like Apache and NGI...]]></description><link>https://blog.billvanleeuwen.ca/writing-an-http-server-in-c</link><guid isPermaLink="true">https://blog.billvanleeuwen.ca/writing-an-http-server-in-c</guid><category><![CDATA[C]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[Bill Van Leeuwen]]></dc:creator><pubDate>Thu, 26 May 2022 17:07:37 GMT</pubDate><content:encoded><![CDATA[<p>One project I've really been keen to work on for a year or so now has been an <strong>HTTP</strong> server.</p>
<p>I'm not exactly sure why this interested me, but it might have something to do with my facination for critical infrastructure. Http servers like <a target="_blank" href="https://httpd.apache.org/">Apache</a> and <a target="_blank" href="https://www.nginx.com/">NGINX</a> are critical backbones of the web as we know it, and having a general understanding of how they work seemed cool to me. Along with this, when I first had the idea suggested to me on a podcast I was listening to, it seemed like such an unreachable goal.</p>
<p>In my previous semester at university I took a Systems Programming course where we learned <strong>C</strong>, and the basics of interacting with the Linux kernel, which included basic socket programming with <strong>TCP</strong> sockets. With this knowledge, I felt armed and ready to finally build an HTTP server.</p>
<h2 id="heading-getting-started">Getting started</h2>
<p>I honestly didn't feel ready to jump directly into the project. Firstly, I didn't have an amazing understanding of the backbones of this project, mainly <strong>TCP</strong> and HTTP. I picked up <a target="_blank" href="https://www.packtpub.com/product/hands-on-network-programming-with-c/9781789349863">this book</a>, and worked through the first few exercises. These were a <a target="_blank" href="https://github.com/billvanleeuwen424/List-Network-Interface-C">super small program that lists your machines outward facing IP addresses</a>, <a target="_blank" href="https://github.com/billvanleeuwen424/CapitalizeServer">a simple TCP server that will capitalize a string sent to it</a>, and a <a target="_blank" href="https://github.com/billvanleeuwen424/TCPClient">TCP Client</a>.</p>
<p>These were fun little programs to write and taught me a lot of fun C tricks, and how TCP works.</p>
<h2 id="heading-writing-the-server">Writing the server</h2>
<p>After prepping all the knowledge, this wasn't actually too hard. I wasn't aiming to build a competitor to Apache or anything, so this only handles simple <strong>GET</strong> requests, and returns <strong>200, 400, 404, or 500</strong> responses. (<em>I also added</em> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/418"><em>418</em></a><em>, but that was just for fun</em> 😊)</p>
<p>One issue I saw from the start was preventing a <a target="_blank" href="https://en.wikipedia.org/wiki/Directory_traversal_attack">directory traversal exploit</a>. Because the parser is simple, and will go to whatever directory supplied, a malicious actor could add <em>".."</em> to the path, which will go up a directory, and traverse to directories which they should not have access to, and potentially see things they shouldn't. the way I prevented this (Although likely not bulletproof) was to check for ".." at the front of the string, and return a 400 response.</p>
<p>My least favourite thing about writing in C is dealing with strings. Whenever I work with strings in PHP or Python, I feel so darn spoiled. When I work with C, I feel like jumping off a cliff. luckily, building the 200 response was only slightly annoying in this respect. There is always going to be at least one segmentation fault.</p>
<h2 id="heading-closing">Closing</h2>
<p>Overall this was a fun project and I learned a lot. This was a bucket list item for me so I'm happy to finish it up!  </p>
<p><a target="_blank" href="https://github.com/billvanleeuwen424/HTTPServer">https://github.com/billvanleeuwen424/HTTPServer</a></p>
]]></content:encoded></item></channel></rss>