Jekyll2018-01-20T04:02:29+00:00https://yurovsky.github.io//var/log/andreyMy blog about Linux systems programming, firmware, and cars.Button (or other GPIO pin) debouncing2017-05-28T00:00:00+00:002017-05-28T00:00:00+00:00https://yurovsky.github.io/2017/05/28/button-or-other-gpio-pin-debouncing<p>(this is mostly a repost from <a href="http://yurovsky.blogspot.com/2011/02/button-or-other-gpio-pin-debouncing.html">back in 2011 on my old blog</a> but I keep referring to it so I wanted it in an easier place to find)</p>
<p>GPIO pin de-bouncing is a fairly common task and there are many good ways to implement it. Here’s how I handle it on most projects, I think that it’s fairly
clean and easy to adapt to small microcontrollers or even some larger systems.</p>
<p>Each pin that needs to be sampled and debounced can be represented with a state machine comprised of a state, value, and counter. A pin is either idle (whether pressed or released) or in transition to being pressed or released. To transition to the idle state, the pin must maintain the same level for a number of counts.</p>
<p>A pin can therefore be represented something like:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">pin_state</span> <span class="p">{</span>
<span class="n">PIN_IDLE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
<span class="n">PIN_PRESSING</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
<span class="n">PIN_RELEASING</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
<span class="p">};</span>
<span class="k">struct</span> <span class="n">pin</span> <span class="p">{</span>
<span class="k">enum</span> <span class="n">pin_state</span> <span class="n">state</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">pressed</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">debounce</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">debounce_threshold</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>
<p>I use three states but with the combination of ‘state’ and ‘pressed’ and ‘debounce’ we really have four real states (idle-pressed, idle-released, pressing, and releasing).</p>
<p>At initialization time, the pin structure(s) should be set to zero. The ‘pin’ structure should also contain information about the pin to enable a routine to check its value (for example the GPIO port and pin number). We then poll the pin or pins in a thread or main loop. For example, to check just one pin:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">struct</span> <span class="n">pin</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* (if needed) */</span>
<span class="n">memset</span><span class="p">(</span><span class="o">&</span><span class="n">pin</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">pin</span><span class="p">));</span>
<span class="cm">/* pick some reasonable threshold, this is a
factor of your circuit and polling
frequency */</span>
<span class="n">pin</span><span class="p">.</span><span class="n">debounce_threshold</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">check_pins</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* invert this if the pin is active-low, as is common
for buttons, we treat a '1' as 'active' */</span>
<span class="kt">char</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">gpio_get_pin_value</span><span class="p">();</span>
<span class="k">switch</span> <span class="p">(</span><span class="n">pin</span><span class="p">.</span><span class="n">state</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">PIN_IDLE</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="n">pin</span><span class="p">.</span><span class="n">pressed</span><span class="p">)</span> <span class="p">{</span>
<span class="n">pin</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">cur</span> <span class="o">?</span>
<span class="n">PIN_PRESSING</span> <span class="o">:</span> <span class="n">PIN_RELEASING</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">PIN_PRESSING</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span>
<span class="n">pin</span><span class="p">.</span><span class="n">debounce</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">pin</span><span class="p">.</span><span class="n">debounce</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">pin</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">PIN_IDLE</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">PIN_RELEASING</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="p">{</span>
<span class="n">pin</span><span class="p">.</span><span class="n">debounce</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">pin</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">PIN_IDLE</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">pin</span><span class="p">.</span><span class="n">debounce</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pin</span><span class="p">.</span><span class="n">state</span> <span class="o">></span> <span class="n">PIN_IDLE</span> <span class="o">&&</span>
<span class="n">pin</span><span class="p">.</span><span class="n">debounce</span> <span class="o">></span> <span class="n">pin</span><span class="p">.</span><span class="n">debounce_threshold</span><span class="p">)</span> <span class="p">{</span>
<span class="cm">/* report the pin press or release */</span>
<span class="n">report_pin</span><span class="p">(</span><span class="n">cur</span><span class="p">);</span>
<span class="cm">/* and now the pin is idle */</span>
<span class="n">pin</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">PIN_IDLE</span><span class="p">;</span>
<span class="n">pin</span><span class="p">.</span><span class="n">debounce</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">pin</span><span class="p">.</span><span class="n">pressed</span> <span class="o">=</span> <span class="n">cur</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>If there are multiple pins to check then I would replace the single
<code class="highlighter-rouge">struct pin</code> with an array and loop over them.
In that case <code class="highlighter-rouge">struct pin</code> should contain pin port and pin number information
for your implementation of <code class="highlighter-rouge">gpio_get_pin_value()</code>.</p>
<p>When debouncing a physical button we generally shoot for around 50ms (that is,
a level change below 50ms is filtered out). We usually wind up with 47ms when
debouncing with an RC circuit (typical values are a 4.7k Ohm resistor and a 100nF capacitor making RC equal to 47ms) so either one seems like a good target.</p>
<p>The very generic state machine described above just uses a counter and this can
be calculated or experimentally calibrated to the system based on the behavior
of that system’s GPIOs. If there is a time source available, for example a timer block or an RTC with reasonable precision, this counter be
replaced with a time stamp and it’s much easier to set the time threshold for
debouncing.</p>(this is mostly a repost from back in 2011 on my old blog but I keep referring to it so I wanted it in an easier place to find)Developing STM8 boot code with SDCC2017-04-18T00:00:00+00:002017-04-18T00:00:00+00:00https://yurovsky.github.io/2017/04/18/stm8-boot-code-sdcc<p>I’m using the open source <a href="http://sdcc.sourceforge.net/">SDCC</a> toolchain to
develop an application for the STM8
microcontroller and part of that requires a custom bootloader (what ST’s
manuals refer to as User Boot Code or UBC) and application firmware. Here are
some notes on how to use SDCC and <a href="https://github.com/vdudouyt/stm8flash">stm8flash</a> to develop and flash the bootloader and application.</p>
<p>The UBC concept itself is mostly a convention on STM8. The hardware does not
do much with it aside from treating the UBC area of flash as write-protected
(the idea is that boot code is not field-upgradeable in a typical product
whereas we may wish to reflash the application firmware).</p>
<h1 id="boot-process-and-interrupts">Boot process and interrupts</h1>
<p>The STM8 uses option byte 1 to determine the size of the UBC (it’s 0 by default
meaning there is no boot code). Setting this to a non-zero size reserves a
portion of flash (starting at <code class="highlighter-rouge">0x8000</code>) for the UBC. For example setting byte 1
to 4 reserves four 256 byte blocks or 1KB for the UBC.</p>
<p>It is up to the boot code to jump to the application. The STM8 CPU assumes that
the interrupt vector table is located at <code class="highlighter-rouge">0x8000</code> so this single table must be
shared between the UBC and the application.</p>
<h2 id="interrupt-vector-table">Interrupt vector table</h2>
<p>In SDCC, interrupt vectors look like:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">usart1_rx_irq</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__interrupt</span><span class="p">(</span><span class="mi">28</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Interrupt vectors must be implemented in the same translation unit (file) that
implements <code class="highlighter-rouge">main()</code> and the <code class="highlighter-rouge">__interrupt</code> attribute is used to specify their
IRQ number (which becomes an offset into the interrupt vector table).</p>
<p>The interrupt vector table is placed at the start of the program (<code class="highlighter-rouge">0x8000</code> by
default, or whatever is set by using the <code class="highlighter-rouge">--code-loc</code> option). The UBC will be
placed at <code class="highlighter-rouge">0x8000</code> along with its vector table but the application needs to be
placed after the UBC (starting with its own vector table). So for a 1KB UBC
(that is, option byte 1 is set to 4) we would build the application firmware
with <code class="highlighter-rouge">--code-loc=0x8400</code> and we know that the interrupt vector table for the
application is at <code class="highlighter-rouge">0x8400</code>.</p>
<p>The STM8 manual shows the offsets from the start of the vector table for each
interrupt handler. For the above interrupt 28, the offset is 0x78. Assuming the
boot code does not need to do anything with interrupt 28, we could simply
redirect to the application firmware’s implementation of that interrupt handler.
That is, in the UBC we would have something like:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">usart1_rx_irq</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__interrupt</span><span class="p">(</span><span class="mi">28</span><span class="p">)</span>
<span class="p">{</span>
<span class="kr">__asm</span> <span class="n">jpf</span> <span class="mh">0x8478</span> <span class="n">__endasm</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>To connect the real interrupt 28 to the redirected handler in the application’s
table. The application’s implementation of interrupt 28 would do whatever it
is that is appropriate for handling that interrupt.</p>
<p>The UBC should redirect every single interrupt to the right location to provide
equivalent functionality in the application. The table itself contains 4-byte
entries:</p>
<ul>
<li>0x00: the reset vector</li>
<li>0x04: trap handler</li>
<li>0x08: interrupt 0 (unused)</li>
<li>0x0C: interrupt 1 (FLASH)</li>
<li>0x10: interrupt 2 (DMA 0/1)</li>
</ul>
<p>…and so on. As such, interrupt 28 is <code class="highlighter-rouge">4 * 28 + 8</code> or <code class="highlighter-rouge">120</code> which gives us the
offset <code class="highlighter-rouge">0x78</code> and, if the application starts at <code class="highlighter-rouge">0x8400</code> the redirected vector
is at <code class="highlighter-rouge">0x8478</code>.</p>
<p>We can calculate some offsets and addresses in code (or the preprocessor) to
make life easier.</p>
<h1 id="stm8flash">stm8flash</h1>
<p>To flash the MCU:</p>
<ul>
<li>get the current option bytes content from the MCU</li>
<li>modify that content to set the UBC size (and any other changes needed)</li>
<li>write back the modified option bytes</li>
<li>write the bootloader</li>
<li>write the application</li>
</ul>
<p>Using the STM8 discovery board (with STM8L151), we can read the option bytes
from the MCU,</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stm8flash -c stlink -p stm8l151?6 -s opt -r opt.bin
</code></pre></div></div>
<p>Then edit <code class="highlighter-rouge">opt.bin</code> as needed. Note that byte 0 must always be set to <code class="highlighter-rouge">0xAA</code> to
keep the SWIM protocol usable. To write it back:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stm8flash -c stlink -p stm8l151?6 -s opt -w opt.bin
</code></pre></div></div>
<p>To write the bootloader, <code class="highlighter-rouge">boot.ihx</code> to the default location (0x8000):</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stm8flash -c stlink -p stm8l151?6 -w boot.ihx
</code></pre></div></div>
<p>And then to write the application to (for example) 0x8400:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stm8flash -c stlink -p stm8l151?6 -s 0x8400 -w fw.ihx
</code></pre></div></div>
<h1 id="self-programming-the-flash">Self-programming the Flash</h1>
<p><em>Warning</em>: this is going to get very hacky!</p>
<p>One of the typical tasks of a bootloader is accepting a new application to
write into the application section of the Flash. There isn’t much Flash on a
typical STM8 microcontroller so we’re likely to implement a scheme that
involves:</p>
<ul>
<li>the application is told to jump to boot code and accept a firmware update</li>
<li>the boot code starts and, rather than jumping to the application, waits for new firmware</li>
<li>new firmware is received and written to the Flash, block by block</li>
<li>having completed the reflashing process, the boot code is told to boot the new application</li>
</ul>
<p>That’s generally easy enough to implement but on STM8 (and many other parts) an
efficient block-oriented Flash operation requires us to be executing from RAM
rather than in-place in the Flash. This requires us to place the actual code
that performs the erase and write operation into RAM as well as the block of
data that we wish to write.</p>
<h2 id="unlocking-the-flash">Unlocking the Flash</h2>
<p>The STM8 program flash is unlocked with the following sequence:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">FLASH</span><span class="o">-></span><span class="n">PUKR</span> <span class="o">=</span> <span class="n">FLASH_RASS_KEY1</span><span class="p">;</span>
<span class="n">FLASH</span><span class="o">-></span><span class="n">PUKR</span> <span class="o">=</span> <span class="n">FLASH_RASS_KEY2</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">FLASH</span><span class="o">-></span><span class="n">IAPSR</span> <span class="o">&</span> <span class="n">FLASH_FLAG_PUL</span><span class="p">));</span>
</code></pre></div></div>
<p>The Flash can be erased and written after that.</p>
<h2 id="calling-a-ram-function">Calling a RAM function</h2>
<p>Unfortunately SDCC is missing linker features to help us do this. We cannot
tell the linker to place a routine in RAM and, to make matters worse, we cannot
use a linker-derived symbol in our C code to implement a simple <code class="highlighter-rouge">memcpy()</code> of
the function in question from Flash to RAM, nor can we learn the length of the
function (all things that GCC and proprietary stm8 toolchains can do).</p>
<p>I decided to work around this limitation by taking my own hacky approach:</p>
<ul>
<li>write a dummy program that implements my RAM function, <code class="highlighter-rouge">flash_write_block</code> and compile it with SDCC like any other C program</li>
<li>use the assembly output to locate the implementation of <code class="highlighter-rouge">flash_write_block</code> and retrieve the sequence of bytes (machine instructions) that make this function.</li>
<li>save those bytes as a C array and include it in my bootloader program as static data.</li>
<li>at boot, <code class="highlighter-rouge">memcpy()</code> that array to a location in RAM and call that location. This causes <code class="highlighter-rouge">flash_write_block()</code> to execute in RAM and then return.</li>
</ul>
<p>We need a location for the “array” in RAM to jump to. SDCC provides an <code class="highlighter-rouge">__at</code> attribute to enable us to place a variable at a set location. The static array will have an underscore in front of its name (by my convention) so I decided on:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__at</span><span class="p">(</span><span class="mh">0x400</span><span class="p">)</span> <span class="kt">char</span> <span class="n">_flash_write_block_ram</span><span class="p">[</span><span class="k">sizeof</span><span class="p">(</span><span class="n">_flash_write_block</span><span class="p">)];</span>
</code></pre></div></div>
<p>This function needs to know two things:</p>
<ul>
<li>the location of a block of data to write (128 bytes on my STM8 target)</li>
<li>the destination to write to</li>
</ul>
<p>The data to write must also be in RAM so I selected a fixed location in RAM to
hold that block using SDCC’s <code class="highlighter-rouge">__at</code> attribute:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__at</span><span class="p">(</span><span class="mh">0x380</span><span class="p">)</span> <span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">128</span><span class="p">];</span>
</code></pre></div></div>
<p>I decided to make the destination a “block number” where 0 is the first block of application firmware. My application starts after the UBC, for example at <code class="highlighter-rouge">0x8400</code> so block 0 is address <code class="highlighter-rouge">0x8400</code> and block 1 is <code class="highlighter-rouge">0x8480</code> (the next block).
I can push this to the stack (as an argument to <code class="highlighter-rouge">flash_write_block()</code> or, since the data is in RAM anyway, we can make a RAM location to store this as well:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__at</span><span class="p">(</span><span class="mh">0x37C</span><span class="p">)</span> <span class="kt">uint32_t</span> <span class="n">block</span><span class="p">;</span>
</code></pre></div></div>
<p>In the bootloader’s <code class="highlighter-rouge">main()</code>, we simply copy from Flash to RAM:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">memcpy</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x400</span><span class="p">,</span> <span class="n">_flash_write_block_ram</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">_flash_write_block</span><span class="p">));</span>
</code></pre></div></div>
<p>then, whenever we need to call <code class="highlighter-rouge">flash_write_block()</code> in RAM, we simply write
the data block and block number to the defined locations and call. For example,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">block</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="cm">/* Write to the 0th block of the application */</span>
<span class="kr">__asm</span> <span class="n">call</span> <span class="mh">0x400</span><span class="p">;</span> <span class="n">__endasm</span>
</code></pre></div></div>
<p>…and whatever is in <code class="highlighter-rouge">data</code> will be written to <code class="highlighter-rouge">0x8400</code>.</p>
<h2 id="implementing-the-ram-function">Implementing the RAM function</h2>
<p>The STM8 reference manual describes several ways to program the Flash. I chose
the following:</p>
<ul>
<li>erase the target block</li>
<li>wait for Flash operation to finish</li>
<li>request “fast” block programming (we’ll program all 128 bytes, and the block was already erased)</li>
<li>write all 128 bytes to the target block</li>
<li>wait for Flash operation to finish</li>
</ul>
<p>The data to write is at arbitrary RAM location <code class="highlighter-rouge">0x380</code> and the block number is
at <code class="highlighter-rouge">0x37C</code>. We also need a loop counter for later (and SDCC does not support
variable declarations mixed with code).</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include "stm8l15x.h"
</span>
<span class="cp">#define BOOT_SIZE 0x400 </span><span class="cm">/* This must match the UBC setting as well */</span><span class="cp">
#define APP_BASE (0x8000 + BOOT_SIZE)
</span>
<span class="kt">void</span> <span class="nf">flash_write_block</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">unsigned</span> <span class="n">i</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">block</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x37C</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">APP_BASE</span> <span class="o">+</span> <span class="p">(</span><span class="n">FLASH_BLOCK_SIZE</span> <span class="o">*</span> <span class="n">block</span><span class="p">);</span>
<span class="kt">uint8_t</span> <span class="o">*</span><span class="n">dest</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">addr</span><span class="p">);</span>
<span class="kt">uint8_t</span> <span class="o">*</span><span class="n">data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x380</span><span class="p">;</span>
</code></pre></div></div>
<p>We now know where to write so let’s start by erasing the block. This is done
by requesting an erase operation and then writing <code class="highlighter-rouge">0</code> to the first word in the
block:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> FLASH->CR2 |= FLASH_CR2_ERASE;
*((uint32_t *)(addr)) = 0;
</code></pre></div></div>
<p>We then wait for the operation to finish:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> while (FLASH->IAPSR & (FLASH_IAPSR_EOP | FLASH_IAPSR_WR_PG_DIS));
</code></pre></div></div>
<p>Now we can request block programming (specifically the “fast” version):</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> FLASH->CR2 |= FLASH_CR2_FPRG;
</code></pre></div></div>
<p>To program, we simply copy <code class="highlighter-rouge">data</code> to <code class="highlighter-rouge">dest</code> (we can’t call <code class="highlighter-rouge">memcpy()</code> since it
is not in RAM):</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> for (i = 0; i < FLASH_BLOCK_SIZE; i++)
dest[i] = data[i];
</code></pre></div></div>
<p>That should do it! Now wait for the operation to finish:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> while (FLASH->IAPSR & (FLASH_IAPSR_EOP | FLASH_IAPSR_WR_PG_DIS));
}
</code></pre></div></div>
<p>and we are done. SDCC will label this function <code class="highlighter-rouge">_flash_write_block</code> in the
assembly output. In my hacky scheme, I need a header file such as <code class="highlighter-rouge">ramfunc.h</code>
that has something like:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#pragma once
static char _flash_write_block[] = { /* the instructions */ };
</code></pre></div></div>
<p>to make this whole thing work.</p>
<h2 id="retrieving-instructions-for-ram">Retrieving instructions for RAM</h2>
<p>Normally we could identify where in a binary the target function is implemented
and indeed SDCC lets us know through the linker map file. That said, the linker
does not make a binary (it makes an Intel hex by default) and I don’t have much
information beyond that to help me. After fighting with the SDCC toolchain a
while I decided to “scrape” the assembly file for the dummy program implementing
the <code class="highlighter-rouge">flash_write_block()</code> function to retrieve the machine instructions needed.</p>
<p>This isn’t my proudest moment but I need to get things working and I didn’t see a reliable path forward from the linker’s output. The dummy program just needs:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#include "stm8l15x.h"
#define BOOT_SIZE 0x400 /* This must match the UBC setting as well */
#define APP_BASE (0x8000 + BOOT_SIZE)
void flash_write_block(void)
{
/* the implementation, shown above */
}
void main(void)
{
flash_write_block(); /* I want to see it called */
while (1);
}
</code></pre></div></div>
<p>Having compiled this dummy program, SDCC will leave us with a few interesting
files, the most interesting to me being the listing (<code class="highlighter-rouge">.lst</code>) file.</p>
<p>The assembly listing will show the function starting with:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 000000 115 _flash_write_block:
</code></pre></div></div>
<p>That is, an underscore, the name, and a colon (it’s a label). The last
instruction in the function should of course be a <code class="highlighter-rouge">ret</code></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 00006F 81 [ 4] 193 ret
</code></pre></div></div>
<p>So we just need to grab the instructions (column 2 above, for instance <code class="highlighter-rouge">0x81</code>
is the STM8 <code class="highlighter-rouge">ret</code> instruction) and write them into an array. A more complex
line may look like:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 000060 A3 00 80 [ 2] 184 cpw x, #0x0080
</code></pre></div></div>
<p>And our array should have <code class="highlighter-rouge">0xA3, 0x00, 0x80,</code> corresponding to this.</p>
<p>There are a few ways to do this but I wound up writing a quick and dirty Python
script to do it. It takes a path to a <code class="highlighter-rouge">.lst</code> file and a function to “extract”
and creates an output file (C header file) with the resulting instructions.</p>
<p>This again isn’t my proudest moment but, hey, we’re getting very hacky here:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def load(f, fname, outfile):
found = False
for line in f:
fields = line.split()
if found:
if len(fields) >= 2:
if fields[1] == '81':
found = False
write_out(fields, outfile, found)
else:
if fields[len(fields) - 1] == fname + ':':
outfile.write('#pragma once\n\nstatic char ' + \
fname + '[] = { ')
found = True
outfile.write('};')
</code></pre></div></div>
<p>The <code class="highlighter-rouge">load()</code> method above should capture everything given a function <code class="highlighter-rouge">fname</code>
from an input file <code class="highlighter-rouge">f</code> and write a C header file to <code class="highlighter-rouge">outfile</code>. It’s not doing
much error checking at all and we assume that it’s handed sane input with a
<code class="highlighter-rouge">0x81</code> instruction to finish things off.</p>
<p>For reference, the output file corresponding to the function I described here
gives me, at this time:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#pragma once
static char _flash_write_block[] = { 0x52, 0x08, 0xAE, 0x03, 0x7C, 0x89, 0xEE, 0x02, 0x51, 0x85, 0xFE, 0x9F, 0x88, 0xA6, 0x07, 0x90, 0x58, 0x09, 0x01, 0x02, 0x49, 0x01, 0x4A, 0x26, 0xF6, 0x84, 0x72, 0xA9, 0x84, 0x00, 0xA9, 0x00, 0x02, 0xA9, 0x00, 0x95, 0x17, 0x05, 0x1F, 0x03, 0x1E, 0x05, 0x1F, 0x01, 0xAE, 0x50, 0x51, 0xF6, 0xAA, 0x20, 0xF7, 0x1E, 0x05, 0x90, 0x5F, 0xEF, 0x02, 0xFF, 0xAE, 0x50, 0x54, 0xF6, 0xA5, 0x05, 0x26, 0xF8, 0xAE, 0x50, 0x51, 0xF6, 0xAA, 0x10, 0xF7, 0x5F, 0x1F, 0x07, 0x16, 0x01, 0x72, 0xF9, 0x07, 0x1E, 0x07, 0x1C, 0x03, 0x80, 0xF6, 0x90, 0xF7, 0x1E, 0x07, 0x5C, 0x1F, 0x07, 0x1E, 0x07, 0xA3, 0x00, 0x80, 0x25, 0xE7, 0xAE, 0x50, 0x54, 0xF6, 0xA5, 0x05, 0x26, 0xF8, 0x5B, 0x08, 0x81};
</code></pre></div></div>
<p>…and that does the trick.</p>I’m using the open source SDCC toolchain to develop an application for the STM8 microcontroller and part of that requires a custom bootloader (what ST’s manuals refer to as User Boot Code or UBC) and application firmware. Here are some notes on how to use SDCC and stm8flash to develop and flash the bootloader and application.Building your own Microblaze toolchain from source2017-03-30T00:00:00+00:002017-03-30T00:00:00+00:00https://yurovsky.github.io/2017/03/30/build-microblaze-toolchain<p>I recently needed to work with a synthesized Microblaze CPU set up as a
microcontroller. After using Vivado to generate the initial SDK I decided to
work through building a toolchain from source.</p>
<p>There are two Microblaze worlds, so to speak. The big ones configured with an
MMU are able to run Linux, and for those we have pre-packaged toolchains such
as <code class="highlighter-rouge">gcc-microblaze-linux-gnu</code> in Fedora. For the small ones (no MMU, meant to
run bare-metal or an RTOS) one typically uses the Vivado-supplied GCC toolchain
however that may be outdated (GCC 5.2 in Vivado 2016.04 for example) and may
not have features that you require. Furthermore the Vivado-supplied toolchain
was for some reason built for a 32-bit x86 host.</p>
<h1 id="sources">Sources</h1>
<p>Microblaze support seems to be open-sourced and generally available, however
Xilinx do not make much effort to get their changes into mainline so we need to
use Xilinx’s forks of various projects in order to build something that can
compile and link for Microblaze. Luckily Xilinx maintains a <a href="https://www.xilinx.com/guest_resources/gnu/">Registered Guest Resources</a> site where we can obtain
source snapshots for anything open-source that they utilize. There we find
source archives for the entire toolchain, either the <a href="https://www.xilinx.com/guest_resources/member/mb_gnu/mb-gnu-20161303.tgz">GCC 5.2</a> that is shipped in
Vivado 2016.04 or at this time a <a href="https://www.xilinx.com/guest_resources/member/mb_gnu/mb-gnu-20170306.tar.gz">GCC 6.2</a> as well. These contain:</p>
<ul>
<li>GCC</li>
<li>GDB</li>
<li>binutils (Xilinx’s changes don’t appear to be in mainline)</li>
<li>newlib (the standard C library implementation for small systems)</li>
</ul>
<p>Extract the archive and then untar the contents (each source snapshot is a
tarball inside that archive).</p>
<h1 id="cosstool-ng">cosstool-ng</h1>
<p>The toolchain itself is built by utilizing the crosstool-ng toolchain builder.
Xilinx maintain <a href="https://github.com/Xilinx/crosstool-ng">their own fork of crosstool-ng</a> with some Microblaze-specific changes. I chose to use that, though
the top-level Makefile needed changes from mainline crosstool-ng in order to
build (I patched the Xilinx fork with changes from mainline).</p>
<p>As a starting point, I used the <a href="https://github.com/Xilinx/crosstool-ng/tree/xlnx/master/samples/microblaze-xilinx-elf">samples/microblaze-xilinx-elf</a> configuration as the crosstool-ng <code class="highlighter-rouge">.config</code> and then ran <code class="highlighter-rouge">make menuconfig</code>. Note that
experimental support (<code class="highlighter-rouge">CT_EXPERIMENTAL</code>) is enabled: this is required for
Microblaze to be an option in crosstool-ng.</p>
<h2 id="setup">Setup</h2>
<p>We need to build crosstool-ng but we don’t have to install it (it can be run
from its source directory). To do that:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./configure --enable-local
make
</code></pre></div></div>
<p>The <code class="highlighter-rouge">ct-ng</code> binary will be run to use crosstool-ng.</p>
<h2 id="configuration">Configuration</h2>
<p>Copy the sample configuration file to <code class="highlighter-rouge">.config</code> and then run
<code class="highlighter-rouge">ct-ng menuconfig</code> to further configure the toolchain. The options you should
configure include:</p>
<ul>
<li>no MMU</li>
<li>set endianness to match your synthesized target (the default is big-endian)</li>
<li>build a multilib toolchain (that way you can adjust compilation based on selected Microblaze CPU options, for example the barrel shifter is optional)</li>
<li>build a sysrooted toolchain using cross-compilation</li>
<li>the target operating system is <code class="highlighter-rouge">bare-metal</code></li>
<li>the target binary format is ELF</li>
<li>for <code class="highlighter-rouge">binutils</code>, configure with <code class="highlighter-rouge">--disable-sim</code>, the simulator will not build for microblaze and you’re unlikely to need it, so turn it off.</li>
<li>for <code class="highlighter-rouge">gcc</code>, enable LTO support but disable graphite: unfortunately the library graphite needs to do its work will not build for microblaze at this time.</li>
<li>for <code class="highlighter-rouge">newlib</code>, enable space savings</li>
</ul>
<p>Also for each of the tools (gcc, binutils, gdb, etc) configure the source
location to point to the absolute path to your extracted Xilinx source
snapshots.</p>
<h1 id="building">Building</h1>
<p>Save your configuration and then run <code class="highlighter-rouge">./ct-ng make</code>, this will hopefully build the toolchain but it will take a very long time of course. In fact, crosstool-ng
will build a host toolchain first and then use that to build the
cross-toolchain.</p>
<p>If successful, you will now have a directory named <code class="highlighter-rouge">tool-build</code> one level up from your crosstool-ng directory. This contains a <code class="highlighter-rouge">bin</code> directory with the resulting toolchain. Assuming typical options, the toolchain will have a prefix of
<code class="highlighter-rouge">microblaze-xilinx-elf</code> for a big-endian toolchain or <code class="highlighter-rouge">microblazeel-xilinx-elf</code> for little-endian.</p>
<h1 id="trying-things-out">Trying things out</h1>
<p>The Xilinx SDK builds an archive named <code class="highlighter-rouge">libxil.a</code> (the <code class="highlighter-rouge">xil</code> library) which in
turn contains an entry point and some peripheral initialization code. The source code for this is provided and you can rebuild that library as needed, though you can use the pre-built one as-is if you wish. You will find that the linker will require <code class="highlighter-rouge">libxil</code> either way. To test out the new toolchain, supply a path to the <code class="highlighter-rouge">libs</code> directory containing your copy of <code class="highlighter-rouge">libxil.a</code> via the <code class="highlighter-rouge">-L</code> option.</p>
<p>We can ask the toolchain to dump the options which which it was built in order
to sanity-check our configuration:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>microblaze-xilinx-elf-gcc -v
</code></pre></div></div>
<p>Finally, we can build a sample program:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>microblaze-xilinx-elf-gcc -L/path/to/libs foo.c -o foo.elf
</code></pre></div></div>
<p>And we can generate a binary suitable for loading on hardware:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>microblaze-xilinx-elf-objcopy -S -I elf32-big foo.elf -O binary foo.bin
</code></pre></div></div>
<p>(adjust the above for your toolchain prefix/endianness as needed). The ELF
should be usible in the Vivado debugger (a wrapper over GDB), or GDB itself if
you have set up the Xilinx debug bridge, and the binary can be loaded onto the
target if you have some means of doing that beside the debugger.</p>I recently needed to work with a synthesized Microblaze CPU set up as a microcontroller. After using Vivado to generate the initial SDK I decided to work through building a toolchain from source.Testing applications with qemu user mode, automake, and buildroot2017-01-20T00:00:00+00:002017-01-20T00:00:00+00:00https://yurovsky.github.io/2017/01/20/qemu-unit-tests<p>Previously I discussed <a href="http://yurovsky.github.io/2016/12/14/qemu-user-mode/">using qemu user mode to run cross-compiled binaries</a>, now let’s put a few things
together and run unit tests automatically with <a href="https://www.gnu.org/software/automake/manual/html_node/Tests.html">automake’s <code class="highlighter-rouge">make check</code></a>. Then
we’ll integrate everything into a build system (buildroot) and automatically
run cross-compiled tests as part of the build process. This has a number of
advantages including:</p>
<ul>
<li>no need to build for both x86 and ARM</li>
<li>no need to deploy cross-compiled unit tests to a real target or even a <code class="highlighter-rouge">qemu-system-arm</code> machine, they’ll just run on your machine</li>
<li>easy integration and automation in your build system without requiring any additional steps or configurations</li>
</ul>
<p>Many thanks to <a href="https://github.com/ndreys">Andrey Smirnov</a> who explored this
further after discussing qemu user mode with me and figured all of this out
(I’m mostly just writing up notes on what he did).</p>
<h1 id="running-tests-with-automake">Running tests with automake</h1>
<p>automake has a feature called <code class="highlighter-rouge">LOG_COMPILER</code> as part of its <a href="https://www.gnu.org/software/automake/manual/html_node/Parallel-Test-Harness.html">Parallel Test Harness</a> infrastructure. If this variable is set, tests are executed
with the <code class="highlighter-rouge">LOG_COMPILER</code> as a wrapper. The Parallel Test Harness documentation
gives <code class="highlighter-rouge">perl</code> as an example wrapper but we can take advantage of this feature to
wrap our tests with a shell script calling out to qemu in order to run them
directly on our build machine.</p>
<p>We can capture and set this variable from the environment in <code class="highlighter-rouge">configure.ac</code>,
for instance:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AC_SUBST([LOG_COMPILER], ${LOG_COMPILER})
</code></pre></div></div>
<p>It could be set like this when invoking <code class="highlighter-rouge">configure</code>:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>LOG_COMPILER=qemu-wrapper.sh ./configure
</code></pre></div></div>
<p>Of course we’d also include our cross-compilation options as well. We can then
run <code class="highlighter-rouge">make</code> and <code class="highlighter-rouge">make check</code> and we should see that the tests invoked by <code class="highlighter-rouge">make check</code> are now run using <code class="highlighter-rouge">qemu-wrapper.sh</code>. That in turn needs to be some shell
script that runs its first command-line argument using <code class="highlighter-rouge">qemu-arm</code> with appropriate options (such as <code class="highlighter-rouge">-L</code>) set.</p>
<h1 id="running-tests-with-buildroot">Running tests with buildroot</h1>
<p>Now let’s put everything together into a buildroot recipe. I assume you’re
familiar with how buildroot works (if not, please consult <a href="https://buildroot.org/downloads/manual/manual.html">the buildroot manual</a> and familiarize yourself with how <code class="highlighter-rouge">external.mk</code> and recipes work).</p>
<h2 id="add-a-test-runner">Add a test runner</h2>
<p>We need something simple to point <code class="highlighter-rouge">LOG_COMPILER</code> to so we can add that as a
shell script somewhere in your <code class="highlighter-rouge">external/</code> tree. For example, <code class="highlighter-rouge">external/test-runner.sh</code> could look like:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!bin/sh</span>
<span class="nb">exec</span> <span class="k">${</span><span class="nv">HOST_DIR</span><span class="k">}</span>/usr/bin/qemu-arm <span class="nt">-L</span> <span class="k">${</span><span class="nv">STAGING_DIR</span><span class="k">}</span> <span class="nv">$1</span>
</code></pre></div></div>
<p>Keep in mind that <code class="highlighter-rouge">HOST_DIR</code> points to your build output’s <code class="highlighter-rouge">host</code> directory,
containing the host’s toolchain and, in this case, also the <code class="highlighter-rouge">host-qemu</code> executible. Meanwhile the <code class="highlighter-rouge">STAGING_DIR</code> gives us exactly what we need for qemu’s <code class="highlighter-rouge">-L</code>
option.</p>
<p>We can then create a variable that points to this script. For instance, add:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>TEST_RUNNER := $(BR2_EXTERNAL)/test-runner.sh
</code></pre></div></div>
<p>to <code class="highlighter-rouge">external.mk</code>. Now package recipes have access to the <code class="highlighter-rouge">test-runner.sh</code>
script via <code class="highlighter-rouge">TEST_RUNNER</code>.</p>
<h2 id="making-sure-qemu-arm-is-available">Making sure qemu-arm is available</h2>
<p>Enable qemu from the <code class="highlighter-rouge">Host Utilities</code> menu. Specifically you want to turn on:</p>
<ul>
<li>host qemu</li>
<li>Enable Linux user-land emulation</li>
</ul>
<p>You don’t need “Enable system emulation” unless you want to use qemu’s machine
emulator mode.</p>
<p>Packages needing this qemu-based test infrastructure simply need to select
<code class="highlighter-rouge">BR2_PACKAGE_HOST_QEMU</code> as a dependency in their <code class="highlighter-rouge">Config.in</code>. For example,</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config BR2_PACKAGE_EXAMPLE_APP
bool "example-app"
select BR2_PACKAGE_HOST_QEMU
help
This is a our example app.
</code></pre></div></div>
<p>They also need to call out <code class="highlighter-rouge">host-qemu</code> as a dependency in their recipe, for
example for in <code class="highlighter-rouge">example-app.mk</code>, we could have:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>EXAMPLE_APP_DEPENDENCIES = host-qemu
</code></pre></div></div>
<p>Now when <code class="highlighter-rouge">example-app</code> is built, buildroot will build and deploy <code class="highlighter-rouge">qemu-arm</code>
(to <code class="highlighter-rouge">host</code>).</p>
<h2 id="adding-test-hooks-to-a-recipe">Adding test hooks to a recipe</h2>
<p>Given a typical buildroot recipe for our example app, <code class="highlighter-rouge">example-app.mk</code>, all
we need to do is set <code class="highlighter-rouge">LOG_COMPILER</code> for automake and tell buildroot to run
<code class="highlighter-rouge">make check</code> as a post-build step. Setting <code class="highlighter-rouge">LOG_COMPILER</code> is easy by adding
to buildroot’s <code class="highlighter-rouge"><package>_CONF_ENV</code> variable:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>EXAMPLE_APP_CONF_ENV += LOG_COMPILER=$(TEST_RUNNER)
</code></pre></div></div>
<p>Next, we add a post-build hook:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>define example-app-make-check
$(MAKE) -C $(@D) check
endef
EXAMPLE_APP_POST_BUILD_HOOKS += example-app-make-check
</code></pre></div></div>
<p>Now we should see two things:</p>
<ul>
<li>buildroot will add our <code class="highlighter-rouge">LOG_COMPILER</code> variable to the environment when running <code class="highlighter-rouge">configure</code> in this package</li>
<li>having built the package, buildroot will execute <code class="highlighter-rouge">make check</code> in the package build directory and that in turn will run any tests the package provides with <code class="highlighter-rouge">qemu-arm</code></li>
</ul>
<p>To try this out, build the package:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make example-app
</code></pre></div></div>
<p>You should hopefully see the familiar <code class="highlighter-rouge">make check</code> output after the application
is built. Running <code class="highlighter-rouge">file</code> on binaries in the build directory should reveal that
they are in fact ARM binaries!</p>
<p>A failed unit test in the above example will break the build for that package.
You can adjust the implementation slightly if that’s not what you want and you
could even introduce a configuration option in your <code class="highlighter-rouge">external/Config.in</code> menu
to make tests optional or control whether test failures break the build, as
usual there is a lot that can be customized with buildroot.</p>
<h2 id="specifying-which-tests-to-run-in-a-recipe">Specifying which tests to run in a recipe</h2>
<p>We may not want to run every test in the build system. Generally speaking, we
can run most unit tests but we will need to skip shell-based functional tests.
<code class="highlighter-rouge">automake</code> provides a way to do that with the <code class="highlighter-rouge">TESTS</code> environment variable.
For example, if we want to run only “test1” and “test2” we can specify them
like this:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>define example-app-make-check
TESTS="test1 test2" $(MAKE) -C $(@D) -e check
endef
EXAMPLE_APP_POST_BUILD_HOOKS += example-app-make-check
</code></pre></div></div>
<p>The <code class="highlighter-rouge">-e</code> argument tells <code class="highlighter-rouge">make</code> to override variables from the environment and
we override <code class="highlighter-rouge">TESTS</code> (the variable calling out which tests to run) with our own
list. Now <code class="highlighter-rouge">make check</code> will run just those tests.</p>
<h2 id="qemu-and-kernel-version">qemu and kernel version</h2>
<p>The recipe the builds qemu in buildroot, <code class="highlighter-rouge">package/qemu/qemu.mk</code>, performs a check comparing the host’s kernel version to the target’s and will
only succeed if the host version is greater than or equal to the target’s. You
may find that buildroot refuses to build <code class="highlighter-rouge">qemu-arm</code> for you. The reasoning is
explained in <code class="highlighter-rouge">qemu.mk</code>: in user mode, qemu translates system calls, so it’s assumed that the target does not make calls that don’t exist on your host machine.</p>
<p>If this is a problem, you can defeat this check (<code class="highlighter-rouge">HOST_QEMU_COMPARE_VERSION</code>) at your own risk or upgrade your host machine if possible. Alternately, you can
use your own qemu rather than buildroot’s (for example a distribution package or your own build). Generally speaking, it’s unlikely that a unit test is going to make system calls that don’t exist on your host machine but of course it depends on what you’re testing and anything is possible.</p>Previously I discussed using qemu user mode to run cross-compiled binaries, now let’s put a few things together and run unit tests automatically with automake’s make check. Then we’ll integrate everything into a build system (buildroot) and automatically run cross-compiled tests as part of the build process. This has a number of advantages including:Using qemu user mode to run cross-compiled binaries2016-12-14T00:00:00+00:002016-12-14T00:00:00+00:00https://yurovsky.github.io/2016/12/14/qemu-user-mode<p>The qemu CPU emulator is typically used to emulate an entire system, for example
we can use <code class="highlighter-rouge">qemu-system-arm</code> to start a simulated ARM-based machine, boot Linux, and then run whatever software is appropriate. There is also a user mode which lets us run a cross-compiled executable right on our host machine and that can be used for various isolated testing tasks (for instance, running unit tests in the target system architecture).</p>
<p>A useful program does need some libraries however and it may need an environment. qemu user mode takes a number of arguments that can be used to supply these. The <code class="highlighter-rouge">-L</code> option lets us specify the path for the ELF interpreter prefix and we can utilize this to point the emulator to a reasonable set of libraries (for example a target file system sitting on my x86 laptop). Additional environment variables can be set with <code class="highlighter-rouge">-E</code>.</p>
<h2 id="running-a-cross-compiled-program">Running a cross-compiled program</h2>
<p>I have built a BSP using <a href="https://buildroot.org/">buildroot</a> and now have a <code class="highlighter-rouge">target/</code> directory that contains nearly everything that will wind up on my root file system image (but note <a href="https://buildroot.org/downloads/manual/manual.html#faq-why-not-use-target-as-chroot">a few caveats</a>) for this target. I can take advantage of the fact that <code class="highlighter-rouge">target/</code> has everything that is needed to run an executable (that is, there’s a <code class="highlighter-rouge">/lib</code> directory there with libraries in the target architecture) so now I can use qemu to run an executable.</p>
<p>For instance,</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>qemu-arm -L target/ /path/to/some/executable
</code></pre></div></div>
<p>Or to run the cross-compiled ARM <code class="highlighter-rouge">/bin/ls</code> right from the target directory,</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>qemu-arm -L target/ target/bin/ls
</code></pre></div></div>
<p>should work provided the ELF interpreter prefix matches up. In my case <code class="highlighter-rouge">ls</code> is a symlink to <code class="highlighter-rouge">busybox</code> and running <code class="highlighter-rouge">file</code> on that produces:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>file target/bin/busybox
target/bin/busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 4.7.0, not stripped
</code></pre></div></div>
<p>and target/ has <code class="highlighter-rouge">lib/ld-linux.so.3</code> present so passing <code class="highlighter-rouge">-L target</code> gets me a running executable.</p>
<p>In addition, <code class="highlighter-rouge">$?</code> will report the cross-compiled program’s return code correctly so with the help of the target ELF interpreter and libraries I can now run unit tests after building my BSP, those unit tests can run in their native architecture, and I can capture output from them and utilize their return codes (for example via <code class="highlighter-rouge">make check</code> in autotools) like I would expect with native unit tests. Furthermore, the unit test executables themselves never need to leave my build system (that is, they don’t need to wind up on the target root file system or even an emulated device) and I do not need a special build just for running those tests.</p>
<h2 id="unit-testing">Unit Testing</h2>
<p>There’s arguably value in running unit tests on their target CPU (even if that CPU is emulated), for example:</p>
<ul>
<li>Memory alignment will match reality (x86 supports unaligned memory access, ARMv5 does not and we can write C code that will not work on ARMv5)</li>
<li>Math behaves the same (consider a 64-bit x86 machine performing 64-bit arithmetic vs. a 32-bit ARM machine performing the same arithmetic, we can write C programs that will give different results on different CPUs)</li>
<li>We can run tests in their expected target endianness and that can matter even though carefully written code should behave correctly.</li>
</ul>
<p>Unit tests run with qemu user mode would ideally be real testable units since we’re not simulating the entire machine (that is, they should not interact with hardware or other software since they are running on their own) but that is in line with unit testing practices anyhow. Functional tests that need additional software components or hardware can be tested on an emulated machine with qemu system mode.</p>
<h2 id="interactive-debugging-with-gdb">Interactive debugging with GDB</h2>
<p>qemu user mode can act as a GDB server, enabling us to debug our cross-compiled program. Consider the usual trivial program:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Hello, world!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>We can compile this with debug symbols via our toolchain, for example:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>arm-buildroot-linux-gnueabi-gcc -g -c hello.c -o hello.o
arm-buildroot-linux-gnueabi-gcc hello.o -o hello
</code></pre></div></div>
<p>Start qemu with a GDB server on an arbitrary port, for example 12345:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>qemu-arm -L target/ -g 12345 ./hello
</code></pre></div></div>
<p>and it will wait for GDB to attach. We can then run our toolchain GDB (using the debug symbols in <code class="highlighter-rouge">hello</code>):</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>arm-buildroot-linux-gnueabi-gdb ./hello
</code></pre></div></div>
<p>and then, in GDB’s console, connect to the GDB server:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>target remote localhost:12345
</code></pre></div></div>
<p>we should also tell GDB to use our target root file system as the sysroot (since that’s where all the libraries are), this enables GDB to find libc and anything else we may depend on:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set sysroot ./target
</code></pre></div></div>
<p>We can now set breakpoints and debug like we would any other program, for example:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b main
c
</code></pre></div></div>
<p>We’re now able to run and debug our cross-compiled program without needing to boot a real or even emulated machine, provided the program can run on its own without needing access to resources that qemu user mode won’t provide (again in those cases, use <code class="highlighter-rouge">qemu-system-arm</code> to boot an emulated machine running Linux).</p>The qemu CPU emulator is typically used to emulate an entire system, for example we can use qemu-system-arm to start a simulated ARM-based machine, boot Linux, and then run whatever software is appropriate. There is also a user mode which lets us run a cross-compiled executable right on our host machine and that can be used for various isolated testing tasks (for instance, running unit tests in the target system architecture).PID file safety2016-11-11T00:00:00+00:002016-11-11T00:00:00+00:00https://yurovsky.github.io/2016/11/11/pid-file-safety<p>There are some instances where we need to use the old-style PID files in order
to signal a daemon process (typically sending it a <code class="highlighter-rouge">SIGHUP</code> to ask it to
re-read its configuration files or a <code class="highlighter-rouge">SIGTERM</code> to ask the daemon to exit). We
can get our of the business of managing daemons with things like systemd but in
the cases when we still have to deal with PID files, we should be careful.</p>
<p>Typically we have opened a PID file for a hypothetical daemon, <code class="highlighter-rouge">food</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">FILE</span> <span class="o">*</span><span class="n">f</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"/var/run/food.pid"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="p">{</span>
<span class="cm">/* Daemon may be running. */</span>
</code></pre></div></div>
<p>We then need to read in the PID (we expect the file to contain just a number)
so we can send that daemon a signal. This can be as simple as:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pid_t</span> <span class="n">pid</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">fscanf</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s">"%"</span> <span class="n">SCNiMAX</span><span class="p">,</span> <span class="o">&</span><span class="n">pid</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="cm">/* We probably read a PID */</span>
</code></pre></div></div>
<p>It’s very important that we check the result of fscanf(3) as we only want to
proceed if we read something that looks like a number. <a href="http://man7.org/linux/man-pages/man2/kill.2.html">kill(2)</a> is very
dangerous depending on what we do with it and what our privileges are on the
system. For instance, the <code class="highlighter-rouge">pid</code> argument to kill implies:</p>
<ul>
<li>Send the signal to every process that we have permission to if <code class="highlighter-rouge">pid</code> is -1, certainly this would be bad. If <code class="highlighter-rouge">pid</code> is less than -1, the signal will be sent to a particular process group.</li>
<li>Send the signal to every process in the process group of the calling process if <code class="highlighter-rouge">pid</code> is 0, this is also bad.</li>
<li>If <code class="highlighter-rouge">pid</code> is positive, send the signal to that process. However if <code class="highlighter-rouge">pid</code> is 1, we are going to send that process to the init system. If <code class="highlighter-rouge">pid</code> happens to be our own PID, we send the signal to ourselves.</li>
</ul>
<p>The data type for a PID is <code class="highlighter-rouge">pid_t</code> which in the GNU standard C library is an
<code class="highlighter-rouge">int</code>. We should probably check that the PID at least looks like something
sane:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pid_t</span> <span class="n">pid</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">fscanf</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s">"%"</span> <span class="n">SCNiMAX</span><span class="p">,</span> <span class="o">&</span><span class="n">pid</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">&&</span> <span class="n">pid</span> <span class="o">></span> <span class="mi">1</span> <span class="o">&&</span> <span class="n">pid</span> <span class="o">!=</span> <span class="n">getpid</span><span class="p">())</span> <span class="p">{</span>
<span class="cm">/* We probably read a PID and it seems sane */</span>
</code></pre></div></div>
<p>Depending on the application, we may also use <a href="http://man7.org/linux/man-pages/man2/getpid.2.html">getppid(2)</a> to make sure the PID is not the one for our own parent process.</p>
<p>We can then try to check if someone is running with that PID. Traditionally
that is done by sending a 0 signal (a 0 signal means that no signal is actually
sent but error checking is still performed).</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fclose</span><span class="p">(</span><span class="n">f</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">kill</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">errno</span> <span class="o">==</span> <span class="n">ESRCH</span><span class="p">)</span> <span class="p">{</span>
<span class="cm">/* Nothing with that PID seems to exist
(or the process is a zombie) */</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">errno</span> <span class="o">==</span> <span class="n">EPERM</span><span class="p">)</span> <span class="p">{</span>
<span class="cm">/* We don't have permissions to send a signal
to this process */</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="cm">/* We can send signals to this PID, proceed,
for example: */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">kill</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">SIGHUP</span><span class="p">))</span> <span class="p">{</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Couldn't signal %d: %m"</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Finally, if we need to implement the daemon side (double-forking, closing file
descriptors, optionally creating PID files, and so on) please consider linking
against <a href="http://0pointer.de/lennart/projects/libdaemon/">libdaemon</a> rather than
writing the code yourself (see the <a href="http://0pointer.de/lennart/projects/libdaemon/reference/html/index.html">testd.c example</a> for usage).</p>There are some instances where we need to use the old-style PID files in order to signal a daemon process (typically sending it a SIGHUP to ask it to re-read its configuration files or a SIGTERM to ask the daemon to exit). We can get our of the business of managing daemons with things like systemd but in the cases when we still have to deal with PID files, we should be careful.Opening files (and Linux drivers)2016-11-11T00:00:00+00:002016-11-11T00:00:00+00:00https://yurovsky.github.io/2016/11/11/file-io-drivers<p>We should be careful (if not downright paranoid) when opening files. Some of
the recommended checks to perform and best practices include:</p>
<ul>
<li>Using <a href="http://man7.org/linux/man-pages/man3/realpath.3.html">realpath(3)</a> to produce a canonicalized absolute path for us when the path comes from outside.</li>
<li>Setting O_CLOEXEC to make sure that the file descriptor is not leaked to any child processes we spawn</li>
<li>Sanity-checking the file with <a href="http://man7.org/linux/man-pages/man2/stat.2.html">fstat(2)</a> to make sure it looks like the kind of file we are expecting</li>
</ul>
<p>When appropriate, we can also use the fstat(2) output to check for:</p>
<ul>
<li>Expected file ownership (at least with the <code class="highlighter-rouge">st_uid</code> and <code class="highlighter-rouge">st_gid</code>), for example if we expect a specific user and/or group to own the file, regardless of our ability to access it.</li>
<li>An expected physical location (<code class="highlighter-rouge">st_dev</code> field), for example if we expect it to reside on a specific disk or device regardless of what the path says.</li>
<li>Expected permissions (<code class="highlighter-rouge">st_mode</code> field), for example we may want to refuse to open an executable file or a file with too lax of permissions no matter what</li>
</ul>
<h1 id="the-path">The path</h1>
<p>A program taking a path from the outside world, for example through a command
line argument, should sanitize the path (per CERT <a href="https://securecoding.cert.org/confluence/display/c/FIO02-C.+Canonicalize+path+names+originating+from+tainted+sources">FIOO2-C</a>). Typically this looks like:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>int main(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: %s <path>\n", argv[0]);
exit(EXIT_SUCCESS);
}
char *path = realpath(argv[1], NULL);
if (!path) {
fprintf(stderr, "Invalid argument: %m");
</code></pre></div></div>
<p>The resolved path will need to be freed.</p>
<h1 id="example-talking-to-a-spi-spidev-device">Example: Talking to a SPI (spidev) device</h1>
<p>We can now try to open the file given the resolved path, however we should
sanity-check that the file looks like something that we expect to open. For
example, a SPI device interfaced via the Linux spidev driver should at least:</p>
<ul>
<li>Be a character device (and not, say, a regular file or socket)</li>
<li>Have the major 153</li>
</ul>
<p>We specifically want to use fstat(2) rather than stat(2) because we want to
be sure that we are checking the file we opened rather than checking a path
twice (and allowing whatever the path resolves to to change out from under
us).</p>
<p>First, we open the file:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>int fd = open(path, O_CLOEXEC);
if (fd == -1) {
fprintf(stderr, "Unable to open \"%s\"\n", path);
goto out_fd;
}
</code></pre></div></div>
<p>Then we perform some basic sanity checks. The <code class="highlighter-rouge">st_mode</code> field tells us what
kind of file we have and there are convenient macros to simplify our checks:
<code class="highlighter-rouge">ST_IS_CHR</code> checks that this is a character device, which is what we expect.
In order cases we may want a regular file (<code class="highlighter-rouge">S_ISREG</code> matches that).</p>
<p>For character devices and other special files we also have the <code class="highlighter-rouge">st_rdev</code> field
on which we can use macros <code class="highlighter-rouge">major</code> and <code class="highlighter-rouge">minor</code> to check for specific IDs.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct stat st;
if (fstat(fd, &st) || !S_IS_CHR(st.st_mode) || major(st.st_rdev) != 153) {
fprintf(stderr, "\"%s\" does not look like a SPI device\n", path);
goto out_st;
}
</code></pre></div></div>
<p>We have now opened the file and reasonably believe that it is a SPI device.
Our cleanup would be in reverse order:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>out_st:
close(fd);
out_fd:
free(path);
</code></pre></div></div>
<p>or the GCC <a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">cleanup attribute</a> can be used to clean up resources.</p>We should be careful (if not downright paranoid) when opening files. Some of the recommended checks to perform and best practices include:Using spidev with the Linux kernel device tree2016-10-07T00:00:00+00:002016-10-07T00:00:00+00:00https://yurovsky.github.io/2016/10/07/spidev-linux-devices<p>I recently hit a <code class="highlighter-rouge">WARN_ON</code> when adding a spidev device to a device tree, the
warning is:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>buggy DT: spidev listed directly in DT
</code></pre></div></div>
<p>and it was introduced by <a href="http://www.spinics.net/lists/linux-spi/msg03301.html">this patch</a>. This is quite unfortunate but easy to work around, though I would
argue that it’s counter to the point of the <code class="highlighter-rouge">spidev</code> driver to begin with: after
all we’re describing hardware that we’re talking to from user space and there’s
no need to describe it in the device tree, this just creates extra work.</p>
<h2 id="solution-1-the-proper-way">Solution 1: the proper way</h2>
<p>To avoid this warning you will need to add your device to the <code class="highlighter-rouge">spidev_dt_ids</code>
table in <code class="highlighter-rouge">drivers/spi/spidev.c</code> and then use that device string (and not literally <code class="highlighter-rouge">spidev</code> in your device tree <code class="highlighter-rouge">compatible</code>). For example you could add
a device named <code class="highlighter-rouge">foocorp,modem</code> to the end of that table:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">--- a/drivers/spi/spidev.c
</span><span class="gi">+++ b/drivers/spi/spidev.c
</span><span class="gu">@@ -695,6 +695,7 @@
</span> static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
<span class="gi">+ { .compatible = "foocorp,modem" },
</span> {},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
</code></pre></div></div>
<p>And then your device tree entry would contain a node with the corresponding
compatible string:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>compatible = "foocorp,modem";
</code></pre></div></div>
<p>When the <code class="highlighter-rouge">spidev</code> module is probed, things should match up and you will see
a corresponding character device as before.</p>
<h3 id="problems-with-this">Problems with this</h3>
<p>This has some obvious problems including:</p>
<ul>
<li>We now have to patch the kernel to add a string to some code for no apparent
reason other than “correctness” of the device tree.</li>
<li>This patch is probably not going upstream because it’s unlikely that anyone
else has this hardware (though in some cases it may go upstream).</li>
<li>Maintaining this patch is not going to be pleasant: you’re adding an entry
to a table and rebasing will take some work once people add more things to
that table.</li>
</ul>
<h2 id="solution-2-quick-and-dirty">Solution 2: quick and dirty</h2>
<p>You can forgo patching the driver and simply claim one of the already included
devices from the table. It’s not going to make any difference: <code class="highlighter-rouge">spidev</code> will
match that string and move on. So for example I don’t have a “rohm,dh2228fv”
on my board so I could have:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>comptabile = "rohm,dh2228fv"; /* actually my foocorp modem */
</code></pre></div></div>
<p>And things will work fine and I won’t see the nasty <code class="highlighter-rouge">WARN_ON</code> anymore.</p>
<p>A nicer future change would be to move this <code class="highlighter-rouge">spidev_dt_ids</code> table out to the
device tree itself and avoid this altogether but no one has done that yet (at
least as of the 4.8 kernel). A cursory glance through <code class="highlighter-rouge">arm/boot/dts</code> shows
many users of <code class="highlighter-rouge">spidev</code> that will now be seeing the <code class="highlighter-rouge">WARN_ON</code> message.</p>I recently hit a WARN_ON when adding a spidev device to a device tree, the warning is:TFTP server on Fedora2016-02-20T00:00:00+00:002016-02-20T00:00:00+00:00https://yurovsky.github.io/2016/02/20/tftp-server-fedora<p>Here are some quick notes on setting up a TFTP server on Fedora 23. This is
used, for example, to send Linux kernel images and other binaries to a
bootloader on an embedded system.</p>
<p>First, install the packages:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo dnf install -y tftp tftp-server
</code></pre></div></div>
<p>The <code class="highlighter-rouge">tftp</code> itself will allow you to test your configuration by attempting a
file transfer. The default directory for TFTP transfers is
<code class="highlighter-rouge">/var/lib/tftpboot</code>.</p>
<p>The TFTP server works through xinetd so you will need to add a rule that says
<code class="highlighter-rouge">in.tftpd: ALL</code> to <code class="highlighter-rouge">/etc/hosts.allow</code>:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo su -c "echo 'in.tftpd: ALL' >> /etc/hosts.allow"
</code></pre></div></div>
<p>Enable and start the TFTP server:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable tftp
sudo systemctl start tftp
sudo systemctl daemon-reload
</code></pre></div></div>
<p>Tell the firewall to allow TFTP traffic:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo firewall-cmd --permanent --add-service tftp
sudo firewall-cmd --reload
</code></pre></div></div>
<p>You should now be able to transfer files via TFTP.</p>Here are some quick notes on setting up a TFTP server on Fedora 23. This is used, for example, to send Linux kernel images and other binaries to a bootloader on an embedded system.Mercedes W124 E320 Wagon notes2016-02-20T00:00:00+00:002016-02-20T00:00:00+00:00https://yurovsky.github.io/2016/02/20/mercedes-w124-e320-wagon<p>Here are some notes about Mercedes W124 wagon ownership in case the information
is useful to other people. Specifically my experience is with the later E320
wagon (with the DOHC m104 3.2L six).</p>
<p>The Mercedes W124 is a fantastic car and I highly recommend it to anyone who
can handle (and enjoys) doing basic maintenance and repairs themselves. They
are not, however, for the faint of heart or for people who need a shop or
dealer to repair everything on the car – these are somewhat complex cars with
a few potential issues and repairs could get expensive unless you are willing
to research and do a few things yourself, including tracking down used parts
when needed.</p>
<p>The E320 is solid, safe, and quite reliable. The wagon portion is really well
designed for doing wagon things:</p>
<p><img src="/assets/wagon.jpg" alt="E320 Wagon" /></p>
<p>The rear seats fold forward nicely in two sections and latch flat into the
floor, there is a removable cargo cover and cargo net system included, and
the car even
provides two rear-facing seats in the back and is technically able to seat
seven people when needed. The included roof rack works well and is easy to
adjust. The wagons feature a hydraulic self-levelling rear suspension that
handles heavy loads brilliantly.</p>
<p><img src="/assets/wagon-back.png" alt="E320 Wagon Seats Folded" /></p>
<p>The car itself drives better than the popular W123 wagon: it is much more
modern, more comfortable, and smoother. The wagon door provides a soft-close
mechanism much like the W140 S-class trunk latch, and the W124 has quite a
lot more power of course. The later ones have very good brakes (with four
piston front calipers), ABS is standard, and a rudimentary traction control
system called ASR was an option.</p>
<p>All W124s have a driver side air bag and later (1994 and 1995) cars have a
front passenger side air bag. This was added by taking away the glove box
because Mercedes did not want to redesign the dashboard for the two final
years. The center console does have a storage compartment and the front doors
have reasonable storage as well.</p>
<p>Keep in mind that these cars do not have particularly good fuel economy and
they do require premium (91 octane or higher) fuel. The m104 six provides about
the same fuel economy as the 4.2L m119 V8 in the E420 sedan.
It may be the sheer weight of the car plus the 4-speed automatic. Even freeway
fuel consumption is not that great.</p>
<h2 id="our-car">Our car</h2>
<p>The W124 wagon we wound up buying is a 1994 E320 with, as it turns out, nearly
all of the options. Some of the interesting ones include:</p>
<ul>
<li>leather seats (the other option is vinyl)</li>
<li>heated front seats with memory (look for heater switches on either side of the center console ashtray)</li>
<li>adjustable steering column</li>
<li>headlight washer and wiper system</li>
<li>ASR (traction control)</li>
</ul>
<p>All of the US-market wagons (I believe) have the power sunroof standard along
with the rear-facing fold-out seats and cargo cover system. The standard wood
trim is zebrano (zebra wood) like on the W123 but there is also an optional
burl walnut trim.</p>
<h2 id="trailer-hitch">Trailer Hitch</h2>
<p>We use our E320 wagon to tow a Scamp 13-foot trailer. <a href="http://www.curtmfg.com/">Curt Manufacturing</a> makes
a compatible trailer hitch kit that I combined with a generic trailer harness
wiring kit. There is not much to the installation beyond following the Curt
instructions and the wiring is relatively simple: I ran a fused 12V wire from
the battery positive, following some brake lines to the rear of the car, then
tapped into the tail light harness behind the spare tire. I removed the rear
gray “glove box” trim to get to a rubber plug where the harness comes down to
the hitch and also to run one wire over to the passenger side tail light turn
signal wiring. The wire colors were:</p>
<ul>
<li>tail lamp: gray/black or gray/red</li>
<li>brake: black/red</li>
<li>left turn signal: black/white</li>
<li>right turn signal: black/green</li>
</ul>
<p><img src="/assets/camp1.jpg" alt="E320 Wagon With Camper" /></p>
<h2 id="issues-and-things-to-avoid">Issues and Things to Avoid</h2>
<p>There are a number of potential problems or weak points on the W124. They are
easy enough to deal with but it is important to be aware and ready.</p>
<h3 id="4matic">4Matic</h3>
<p>The W124 has the first implementation of 4Matic and it is extremely
complex and trouble-prone, plus parts to repair it are difficult to obtain.
Just avoid the the 4Matic-equipped 300TE or stick with the E320 which was not
offered with 4Matic in the US. <a href="https://en.wikipedia.org/wiki/4Matic">This wikipedia article</a> explains 4Matic.</p>
<h3 id="transmission">Transmission</h3>
<p>The 4-speed automatic in these cars is a Mercedes design and is very reliable
for an automatic. Most used W124 cars are likely to have enough miles
on them to need a transmission rebuild. A replacement transmission runs about
$2500 at this time which given the low cost of the car to begin with is not
really that big of a deal. You may be able to find a car that already has a
new or rebuilt transmission, that is definitely a bonus. The previous owner of
our E320 had the transmission replaced at about 200,000 miles.</p>
<p>These transmissions can fail in a number of ways but a typical warning sign is
difficulty in engaging reverse: if that is happening, a transmission rebuild
is coming soon. A car without working reverse definitely needs a transmission.</p>
<h3 id="wiring">Wiring</h3>
<p>The W124 wagons were made during the range of years in which Mercedes had a
huge problem with wiring harness insulation. The later-model E320 cars like
ours will absolutely have the “wiring problems” so it’s important to know what
harnesses have already been replaced when looking at used cars. There are
actually several wiring harnesses under the hood that can (and will) fail, I
think the total is four separate units if you count the throttle body.</p>
<p>The first one to check is the main fuel injection wiring harness. This starts
at the ECU (behind the battery) and runs to the engine (between the valve cover
and the intake manifold), connecting to the MAF, all injectors, and various
sensors on the front of the engine. This harness is very expensive ($1400 or
so new) but it can be replaced with a used one that was built after the wiring
insulation was improved – the key is the date code on the harness.</p>
<p>The fuel injection harness date code can be found near where the harness plugs into the ECU. To see it open the hood (all the way up via the vertical latches
helps) and remove the plastic ECU cover behind the battery (it’s just stuck
into place, no fasteners). You should hopefully see a white Delphi parts tag
with a date code much newer than the year of the car on this harness, indicating
a replacement part. A date code near the car’s production date or model year
likely indicates the original part and this harness is very likely to fail
soon if it hasn’t already.</p>
<p>Another harness connects to the alternator and starter (this actually failed
on ours) but is much harder to inspect.</p>
<p>Finally, these cars have a partially drive-by-wire (electric) throttle body.
The wiring in the throttle body has the same insulation problem as the fuel
injection harness and will fail. A good warning sign (and our E320 had this)
is non-functional cruise control. The throttle wiring may still fail even if
the cruise control works but a non-functional cruise control tells you that
this is likely the case. Again this throttle can simply be replaced with one
from a newer car (Mercedes used the m104 motor for several more years), I used
one from a newer C-class with a 2003 date code to repair our 1994 E320 and it
worked perfectly. The wiring can also be repaired via a mail-in service offered
by a couple of companies (that will run around $400 or so from what I have read). The throttle does have a date code noted on a parts sticker but it may be very
difficult to see without taking things apart.</p>
<p>There are two variants of the E320 throttle body (and corresponding
idle/throttle control ECU) – one for cars with ASR and another for cars without ASR. They are not interchangeable.</p>
<h3 id="engine">Engine</h3>
<p>The m104 six is considered very reliable, however they are known to have a
weakness in the head gasket and eventually may develop an oil leak toward the
back of the head. Blown head gaskets are not unheard of as well. Our E320 has
well over 226k miles on it and runs fine though (we do not have any records
indicating a rebuild or even a new head gasket but maybe it was done at some
point).</p>
<h3 id="other-issues">Other Issues</h3>
<p>The m104 motors have a less than ideal EGR tube design and these tubes can get
clogged due to a nearly 90-degree bend. I personally have not experienced this
problem but the solution is to clean the tube or replace it with a newer design
part.</p>
<p>Some owners install an off-brand MAF sensor while troubleshooting the car (or
when the MAF genuinely fails). These are known to be junk and indeed my car
came with some off-brand MAF that soon failed. The correct Bosch MAF is very
expensive however I was able to find a cheap used one on eBay and it works fine.</p>
<p>The W124 relies on vacuum to control several subsystems including the HVAC so
make sure that all the dashboard controls are working (note that the top center
vents are not used when heating, that is by design) since that system is hard
to troubleshoot. The power locks and wagon hatch lock are also vacuum-actuated.</p>
<p>The self-levelling rear suspension is very reliable but, when it fails, requires
a more expensive set of parts than a traditional gas shock absorber. I cannot
think of a good way to check this system beyond obvious signs of hydraulic leaks, however I am told that the rear suspension will feel rock-hard and
uncomfortable (little to no dampening) when it fails. I did get to see ours
work in an obvious way several times but that would be hard to do on a test
drive: load the wagon with a lot of heavy things (in my case, hundreds of
pounds of tile for a bathroom remodel) and then start the car and watch the
rear end lift to the right ride height.</p>
<p>I have heard of W124 wagons with leaks in the wagon back area, probably from the hatch itself or one of the side windows. This can result in significant damage or rust so it’s worth checking for. Ours seems to be leak-free.</p>
<p>The rear wagon door hatch struts eventually fail. Replacements aren’t very
expensive and you can install them yourself with a bit of effort (not my
favorite repair job, but I got through it!) to restore operation. The door
is very heavy otherwise.</p>
<p>The W124 is one of the last (if not the last) cars to use the “bullet” (rather
than “blade”) fuses that were popular on German cars. There are two kinds of
“bullet” fuses: ones with a silver color contact and ones with a copper color
contact. The original silver ones are known to build up resistance and cause
circuits to act like they are open (that is, the fuse is blown but it is not
physically blown), causing all sorts of problems. All of the fuses should be
replaced with the copper ones. For example we once noticed that the power
seats and wipers stopped working: replacing the corresponding fuse solved the
problem immediately even though that (silver color contact) fuse was not
blown.</p>Here are some notes about Mercedes W124 wagon ownership in case the information is useful to other people. Specifically my experience is with the later E320 wagon (with the DOHC m104 3.2L six).