<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://embedbits.cz/blog</id>
    <title>EmbedBits Blog</title>
    <updated>2026-10-07T20:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://embedbits.cz/blog"/>
    <subtitle>EmbedBits Blog</subtitle>
    <icon>https://embedbits.cz/img/logo.svg</icon>
    <entry>
        <title type="html"><![CDATA[Debugging a HardFault on a Cortex-M: from a mystery to a line of code]]></title>
        <id>https://embedbits.cz/blog/debugging-hardfault-cortex-m</id>
        <link href="https://embedbits.cz/blog/debugging-hardfault-cortex-m"/>
        <updated>2026-10-07T20:00:00.000Z</updated>
        <summary type="html"><![CDATA[Every embedded developer knows the moment in eight registers on the stack and in four status registers. It is only necessary to read them.]]></summary>
        <content type="html"><![CDATA[<p>Every embedded developer knows the moment: the firmware has been running, and then it does not. The debugger shows that the program sits in an infinite loop with a name like <code>HardFault_Handler</code> or <code>Default_Handler</code>, and the call stack is a few meaningless frames. That loop is the <strong>default</strong> handler of the startup code, and it says exactly nothing about what happened. The fault has a cause, and the processor has already written it down: in eight registers on the stack and in four status registers. It is only necessary to read them.</p>
<p>This article shows how to turn the loop into a line of source code, in two real examples that I ran in QEMU (a model of an STM32F4 board) and examined with GDB: a call of a <code>NULL</code> function pointer and a write to an address where nothing is. All outputs are real.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-core-does-when-a-fault-happens">What the core does when a fault happens<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#what-the-core-does-when-a-fault-happens" class="hash-link" aria-label="Direct link to What the core does when a fault happens" title="Direct link to What the core does when a fault happens" translate="no">​</a></h2>
<p>On a Cortex-M the processor does not crash silently. When it cannot continue (an invalid instruction, a bus error, an access that is not allowed), it takes an <strong>exception</strong> and does two things that are important for the debugging:</p>
<ol>
<li class="">It <strong>pushes eight registers on the stack</strong>: <code>R0</code>, <code>R1</code>, <code>R2</code>, <code>R3</code>, <code>R12</code>, <code>LR</code>, <code>PC</code> and <code>xPSR</code>. The saved <code>PC</code> is the instruction that caused the fault, and the saved <code>LR</code> tells who called the faulting function.</li>
<li class="">It sets <strong>bits in the fault status registers</strong> that say what kind of a fault it was: <code>CFSR</code> (the configurable fault status, which is made of three parts for the memory, the bus and the usage faults), <code>HFSR</code> (the hard fault status) and the address registers <code>MMFAR</code> and <code>BFAR</code> with the address that was accessed.</li>
</ol>
<p>The memory, bus and usage faults have their own handlers, but they are <strong>disabled</strong> after the reset, so every fault is <em>escalated</em> to the HardFault. That is the reason why the one handler sees everything, and the bit <code>FORCED</code> in <code>HFSR</code> says that this has happened.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-handler-that-reads-the-registers">A handler that reads the registers<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#a-handler-that-reads-the-registers" class="hash-link" aria-label="Direct link to A handler that reads the registers" title="Direct link to A handler that reads the registers" translate="no">​</a></h2>
<p>The only difficulty is to get to the stack where the registers are. There are two stack pointers on the core (<code>MSP</code> for the exceptions and the main code, <code>PSP</code> for the tasks of an operating system), and the bit 2 of the value in <code>LR</code> at the entry of the exception tells which of them was used. This has to be done <em>before</em> the compiler uses the stack for its own purposes, so the handler is a short function in assembler (<code>naked</code>: no prologue), which passes the pointer to a function in C:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">fault.c (the report)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ---- the fault report ---- */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">SCB_CFSR</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0xE000ED28u</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression">   </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* configurable fault status */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">SCB_HFSR</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0xE000ED2Cu</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression">   </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* hard fault status */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">SCB_MMFAR</span><span class="token macro property"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0xE000ED34u</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">SCB_BFAR</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0xE000ED38u</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The registers that the core pushed on the stack when the fault happened. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> r0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> r1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> r2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> r3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> r12</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> lr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* where the faulting code was called from */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> pc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* the instruction that caused the fault   */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> xpsr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">stackFrame_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">volatile</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">stackFrame_t</span><span class="token plain"> frame</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain">     cfsr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> hfsr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> mmfar</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> bfar</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">HardFault_Report</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">stackFrame_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">frame</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">__attribute__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">used</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">HardFault_Report</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">stackFrame_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">frame</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">frame </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">frame</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">cfsr  </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> SCB_CFSR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">hfsr  </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> SCB_HFSR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">mmfar </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> SCB_MMFAR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">bfar  </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> SCB_BFAR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"*** HardFault ***\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"PC   "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> frame</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">pc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"LR   "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> frame</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">lr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"xPSR "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> frame</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">xpsr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"CFSR "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">cfsr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"HFSR "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> faultInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">hfsr</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* stay here, so that a debugger can look at the state */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The core uses the main or the process stack, depending on bit 2 of EXC_RETURN (in LR). */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">__attribute__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">naked</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">HardFault_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    __asm__ </span><span class="token keyword" style="font-style:italic">volatile</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"tst   lr, #4        \n"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"ite   eq            \n"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"mrseq r0, msp       \n"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"mrsne r0, psp       \n"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"b     HardFault_Report \n"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Look at the three parts. The structure <code>stackFrame_t</code> is the layout of the eight registers in the order that the core pushes them. The function <code>HardFault_Report()</code> copies them (together with the status registers) into the global variable <code>faultInfo</code>, prints a short report, and then <strong>stays in a loop on purpose</strong>, so a debugger can connect and look at the variable. The assembler stub selects the right stack and jumps to it. In a product, the report would be written to a memory that survives the reset, and the firmware would reset itself, but the principle is the same.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example-1-the-call-of-a-null-pointer">Example 1: the call of a <code>NULL</code> pointer<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#example-1-the-call-of-a-null-pointer" class="hash-link" aria-label="Direct link to example-1-the-call-of-a-null-pointer" title="Direct link to example-1-the-call-of-a-null-pointer" translate="no">​</a></h2>
<p>This is the application with the bug. A callback is registered later, but the code that calls it runs earlier:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">fault.c (the application)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ---- the application with a bug ---- */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token class-name" style="color:rgb(255, 203, 107)">callback_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">callback_t</span><span class="token plain"> onButtonPressed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">      </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* will be registered later: it is NULL at the start */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Pressed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">onButtonPressed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* the bug: the callback is called before it is set */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"start\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Pressed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"never printed\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The program prints <code>start</code>, and then the report:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">start</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">*** HardFault ***</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">PC    0x00000000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">LR    0x08000115</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">xPSR  0x60000000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">CFSR  0x00020000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">HFSR  0x40000000</span><br></div></code></pre></div></div>
<p>Now the reading of it, value by value:</p>
<ul>
<li class=""><strong><code>PC = 0x00000000</code></strong>: the processor tried to execute an instruction at the address zero. Almost always, this means a jump through a <code>NULL</code> function pointer, or a return to a corrupted address.</li>
<li class=""><strong><code>CFSR = 0x00020000</code></strong>: the bit 17 is <code>INVSTATE</code>, "invalid state". The processor attempted to execute in the ARM state, which a Cortex-M does not have. The reason is in the <strong><code>xPSR</code></strong>: its bit 24 is the <code>T</code> bit (Thumb), and here it is zero (<code>0x60000000</code>). The address of a Thumb function has the lowest bit set, and <code>NULL</code> has not, so the jump through the pointer cleared the <code>T</code> bit. That the <code>T</code> bit is zero is the typical fingerprint of a jump to <code>NULL</code>.</li>
<li class=""><strong><code>HFSR = 0x40000000</code></strong>: the bit 30 is <code>FORCED</code>, the fault was escalated to the HardFault from the usage fault, which is not enabled.</li>
<li class=""><strong><code>LR = 0x08000115</code></strong>: the return address, with the lowest bit set (Thumb). It is the address of the <strong>caller</strong>, <code>0x08000114</code>, and that is where the bug is.</li>
</ul>
<p>With the debugger, the last step takes seconds. The QEMU waits for GDB (<code>-S -gdb tcp::1234</code>), and the session:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) break fault.c:64</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) continue</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Breakpoint 1, HardFault_Report (frame=0x2001ffc0) at fault.c:64</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) print/x faultInfo.frame</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">$1 = {r0 = 0xdeadbeef, r1 = 0x80001f4, r2 = 0x8000220, r3 = 0x0, r12 = 0x0,</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      lr = 0x8000115, pc = 0x0, xpsr = 0x60000000}</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) print/x faultInfo.cfsr</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">$2 = 0x20000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) info symbol faultInfo.frame.lr</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Button_Pressed + 7 in section .text</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) list *(faultInfo.frame.lr &amp; ~1u)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">0x8000114 is in Button_Pressed (fault.c:87).</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">82	static callback_t onButtonPressed;      /* will be registered later: it is NULL at the start */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">84	void Button_Pressed(void)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">85	{</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">86	    onButtonPressed();                  /* the bug: the callback is called before it is set */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">87	}</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) x/2i (faultInfo.frame.lr &amp; ~1u) - 4</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   0x8000110 &lt;Button_Pressed+2&gt;:	movs	r3, #0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   0x8000112 &lt;Button_Pressed+4&gt;:	blx	r3</span><br></div></code></pre></div></div>
<p><code>info symbol</code> gives the function, <code>list *</code> gives the line (the one <em>after</em> the call, because that is the return address), and the disassembly shows the instruction pair that is the bug itself: the load of the zero into <code>r3</code> and the <code>blx r3</code>, a call through a register that holds <code>NULL</code>. Note <code>r3 = 0x0</code> in the stacked registers. Without the debugger, the same answer is in one command of the toolchain, which only needs the address from the report and the file with the debug information (<code>-g</code>):</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">$ arm-none-eabi-addr2line -e fault.elf -f 0x08000114</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Button_Pressed</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">fault.c:87</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example-2-a-write-to-an-address-where-nothing-is">Example 2: a write to an address where nothing is<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#example-2-a-write-to-an-address-where-nothing-is" class="hash-link" aria-label="Direct link to Example 2: a write to an address where nothing is" title="Direct link to Example 2: a write to an address where nothing is" translate="no">​</a></h2>
<p>I changed one line of the application: instead of the callback, the function writes to the address <code>0xA0000000</code>, where nothing is mapped in the model of the chip. The report:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">*** HardFault ***</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">PC    0x08000124</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">LR    0x08000199</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">xPSR  0x21000000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">CFSR  0x00008200</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">HFSR  0x40000000</span><br></div></code></pre></div></div>
<p>This time the <code>PC</code> is a <strong>valid address in the flash</strong>, the <code>T</code> bit is set (<code>0x21000000</code>) and <code>CFSR</code> is different: <code>0x8200</code> are two bits, 9 (<code>PRECISERR</code>, a precise data bus error) and 15 (<code>BFARVALID</code>, the register <code>BFAR</code> holds the address). In GDB:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) print/x faultInfo.cfsr</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">$1 = 0x8200</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) print/x faultInfo.bfar</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">$2 = 0xa0000000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(gdb) info symbol faultInfo.frame.pc</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">main + 12 in section .text</span><br></div></code></pre></div></div>
<p><code>BFAR</code> is the address that the program tried to write, <code>PC</code> is the instruction that tried it. Together they say "this instruction wrote to this address", which is the complete description of the problem. If the address is small (<code>0x00000008</code>), it is a <code>NULL</code> pointer to a structure and you are accessing a member. If it looks like data (<code>0x20000000</code> and a bit more), it is a stack or a buffer that you have overrun.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-bits-of-the-cfsr-that-you-will-meet">The bits of the CFSR that you will meet<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#the-bits-of-the-cfsr-that-you-will-meet" class="hash-link" aria-label="Direct link to The bits of the CFSR that you will meet" title="Direct link to The bits of the CFSR that you will meet" translate="no">​</a></h2>
<p>The register is a combination of three registers (each of them has its own byte or two bytes). These are the ones that you will see most often (the two that I observed in the examples are marked):</p>
















































































<table><thead><tr><th>Bit</th><th>Name</th><th>Meaning</th></tr></thead><tbody><tr><td>0</td><td><code>IACCVIOL</code></td><td>the instruction fetch from a region that is not allowed (MPU)</td></tr><tr><td>1</td><td><code>DACCVIOL</code></td><td>the data access to a region that is not allowed (MPU)</td></tr><tr><td>7</td><td><code>MMARVALID</code></td><td>the register <code>MMFAR</code> holds the address</td></tr><tr><td>8</td><td><code>IBUSERR</code></td><td>the bus error on an instruction fetch</td></tr><tr><td><strong>9</strong></td><td><strong><code>PRECISERR</code></strong></td><td><strong>the precise bus error on a data access: <code>PC</code> is the instruction that did it</strong></td></tr><tr><td>10</td><td><code>IMPRECISERR</code></td><td>the imprecise bus error: the instruction has already gone, <code>PC</code> is not reliable</td></tr><tr><td>11, 12</td><td><code>UNSTKERR</code>, <code>STKERR</code></td><td>the bus error while the registers were popped or pushed (often a damaged stack)</td></tr><tr><td><strong>15</strong></td><td><strong><code>BFARVALID</code></strong></td><td><strong>the register <code>BFAR</code> holds the address</strong></td></tr><tr><td>16</td><td><code>UNDEFINSTR</code></td><td>an undefined instruction (executing data, a corrupted code)</td></tr><tr><td><strong>17</strong></td><td><strong><code>INVSTATE</code></strong></td><td><strong>an attempt to execute in the ARM state: a jump to an address with the bit 0 clear</strong></td></tr><tr><td>18</td><td><code>INVPC</code></td><td>an invalid <code>EXC_RETURN</code> (a damaged stack of an exception)</td></tr><tr><td>19</td><td><code>NOCP</code></td><td>an access to a coprocessor that is not enabled (typically the FPU that was not switched on)</td></tr><tr><td>24</td><td><code>UNALIGNED</code></td><td>an unaligned access, when the trap is enabled</td></tr><tr><td>25</td><td><code>DIVBYZERO</code></td><td>a division by zero, when the trap is enabled</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-usually-stands-behind-a-hardfault">What usually stands behind a HardFault<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#what-usually-stands-behind-a-hardfault" class="hash-link" aria-label="Direct link to What usually stands behind a HardFault" title="Direct link to What usually stands behind a HardFault" translate="no">​</a></h2>

































<table><thead><tr><th>What you see</th><th>What it usually is</th></tr></thead><tbody><tr><td><code>PC = 0</code>, <code>INVSTATE</code></td><td>a call through a <code>NULL</code> function pointer, or a return to a corrupted address</td></tr><tr><td><code>PRECISERR</code> and a small <code>BFAR</code></td><td>a <code>NULL</code> pointer to a structure</td></tr><tr><td><code>PRECISERR</code> and <code>BFAR</code> in a peripheral address range</td><td>an access to a peripheral that is not available, for example one whose clock has not been switched on (on some families such an access is a bus error, on others it is silently ignored)</td></tr><tr><td><code>STKERR</code> / <code>UNSTKERR</code>, or a <code>PC</code> that makes no sense</td><td>a stack overflow or a buffer overflow that damaged the return address</td></tr><tr><td><code>NOCP</code> at the first floating point instruction</td><td>the FPU has not been enabled in the startup code</td></tr><tr><td><code>IMPRECISERR</code></td><td>a write that went through a write buffer: the report arrives later than the instruction. For the debugging, the buffering can be switched off (the bit <code>DISABLEDEFWRITEBUF</code> in <code>ACTLR</code>), so the fault becomes precise</td></tr></tbody></table>
<p>I demonstrated the first line of the table and the principle of the second (a bus error with the address in <code>BFAR</code>). The remaining lines are a summary of the usual causes, they follow from the meaning of the bits in the reference manual of the core.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="practice">Practice<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#practice" class="hash-link" aria-label="Direct link to Practice" title="Direct link to Practice" translate="no">​</a></h2>
<ol>
<li class=""><strong>Never leave the default handler as an empty loop.</strong> The handler above is about thirty lines, and it turns the fault into a report with a place in the code. Put it into the startup code of the project once.</li>
<li class=""><strong>Keep the debug information</strong> in the file that you archive with the release (<code>-g</code>, and the <code>.elf</code>), so the address of a report from the field can be turned into a line, even if the firmware is delivered stripped. That is also one more reason for the <a class="" href="https://embedbits.cz/blog/reproducible-builds-embedded">reproducible build</a>: the address means something only for the exact binary that produced it.</li>
<li class=""><strong>Enable the finer faults</strong> (the bits in <code>SHCSR</code>) when you want the <code>UsageFault</code>, <code>BusFault</code> and <code>MemManage</code> handlers separately. The report is richer, because the status registers are not shared.</li>
<li class=""><strong>Store the report in a memory that survives a reset</strong> (a section that the startup code does not clear, see the article about <a class="" href="https://embedbits.cz/blog/before-main-startup-linker">what happens before <code>main()</code></a>), reset, and send it after the restart. The report of a device in the field is worth more than a hundred guesses.</li>
<li class=""><strong>Prevent what you can.</strong> The <code>NULL</code> call in the example is a defect that the <a class="" href="https://embedbits.cz/blog/misra-c-rules-in-practice">rules of MISRA</a> and a unit test of the module (the pointer must be set before the first call) would catch, and a stack overflow is the thing for which the stack usage has to be known (the rule against the recursion).</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-same-session-on-a-board">The same session on a board<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#the-same-session-on-a-board" class="hash-link" aria-label="Direct link to The same session on a board" title="Direct link to The same session on a board" translate="no">​</a></h2>
<p>I used QEMU, because it does not need a board, and its GDB server (<code>-S -gdb tcp::1234</code>) behaves the same as the one of a debug probe: the commands in the examples are the commands that you type with a probe. The platform has an artifact for the <strong>probe-rs</strong> toolset (a debugging toolset for ARM targets over a debug probe, with a DAP server), which is the way to connect GDB or an IDE to a real board. I did not run it for this article, as I do not have a probe in my environment.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://embedbits.cz/blog/debugging-hardfault-cortex-m#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<ol>
<li class="">A HardFault is not a mystery: the core has pushed the registers and set the status bits.</li>
<li class="">The handler needs to find the right stack (<code>EXC_RETURN</code>) and to read the frame, <code>CFSR</code>, <code>HFSR</code> and <code>BFAR</code>.</li>
<li class=""><code>PC</code> and <code>LR</code> give the place, <code>CFSR</code> gives the kind, <code>BFAR</code> gives the address.</li>
<li class=""><code>PC = 0</code> with <code>INVSTATE</code> is a jump to <code>NULL</code>, and the <code>T</code> bit of the <code>xPSR</code> shows it.</li>
<li class="">Keep the <code>.elf</code>, and the address of a field report becomes a line of code.</li>
</ol>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="STM32" term="STM32"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Running the real firmware without the hardware: a simulator in the CI]]></title>
        <id>https://embedbits.cz/blog/firmware-in-simulator-ci</id>
        <link href="https://embedbits.cz/blog/firmware-in-simulator-ci"/>
        <updated>2026-10-07T18:00:00.000Z</updated>
        <summary type="html"><![CDATA[In the article about unit testing with Unity and CMock I said that the tests on the PC do not find "the differences between the PC and the MCU". This article is about those differences, and about the tool that finds them: a simulator that runs the real binary. Not the logic compiled for the PC, but the very .elf that the ARM compiler made, with the real startup code and the real linker script, on a model of a processor and its peripherals.]]></summary>
        <content type="html"><![CDATA[<p>In the article about <a class="" href="https://embedbits.cz/blog/unit-testing-unity-cmock">unit testing with Unity and CMock</a> I said that the tests on the PC do not find "the differences between the PC and the MCU". This article is about those differences, and about the tool that finds them: a <strong>simulator that runs the real binary</strong>. Not the logic compiled for the PC, but the very <code>.elf</code> that the ARM compiler made, with the real startup code and the real linker script, on a model of a processor and its peripherals.</p>
<p>I will show two experiments that I ran: the same test source that passes on the PC and fails on the Cortex-M4, and a firmware that writes to the registers of a USART at the real addresses of an STM32F4 and whose text appears in the terminal. At the end there is an honest list of what a simulator will not tell you.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-it-fits">Where it fits<a href="https://embedbits.cz/blog/firmware-in-simulator-ci#where-it-fits" class="hash-link" aria-label="Direct link to Where it fits" title="Direct link to Where it fits" translate="no">​</a></h2>





























<table><thead><tr><th>Level</th><th>What runs</th><th>What it finds</th><th>Speed</th></tr></thead><tbody><tr><td><strong>Unit test on the PC</strong></td><td>the logic, compiled for the PC, the layers below mocked</td><td>logic errors</td><td>milliseconds</td></tr><tr><td><strong>Simulator</strong></td><td>the real firmware binary, on a model of the MCU</td><td>the target-specific errors, the startup, the drivers against a register model</td><td>seconds</td></tr><tr><td><strong>Hardware in the loop</strong></td><td>the real firmware on the real MCU with real signals</td><td>timing, the electrical behavior, the real peripherals</td><td>minutes, a lab</td></tr></tbody></table>
<p>The middle level is the one that is skipped most often, and it is the cheapest to add to a CI that already builds the firmware: a simulator is an executable that you start with the file that your build has produced.</p>
<p>The tool in my experiments is QEMU 8.2.2 with the machine <code>netduinoplus2</code>, a model of a board with an <strong>STM32F405</strong> (a Cortex-M4 with the memory map of the real chip: the flash at <code>0x08000000</code>, the RAM at <code>0x20000000</code>, the peripherals at their real addresses). The platform has an artifact for another simulator, <strong>Renode</strong>, and I come back to it at the end.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="experiment-1-the-test-that-passes-on-the-pc-and-fails-on-the-mcu">Experiment 1: the test that passes on the PC and fails on the MCU<a href="https://embedbits.cz/blog/firmware-in-simulator-ci#experiment-1-the-test-that-passes-on-the-pc-and-fails-on-the-mcu" class="hash-link" aria-label="Direct link to Experiment 1: the test that passes on the PC and fails on the MCU" title="Direct link to Experiment 1: the test that passes on the PC and fails on the MCU" translate="no">​</a></h2>
<p>A small module with two functions that every firmware has: the conversion of the time and the check of a received byte.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Conversions.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Conversions.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">long</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Get_Microseconds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> milliseconds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">long</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">milliseconds </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1000L</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Is_HighBitSet</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> receivedByte</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">receivedByte </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Both functions look right, and both are tested on the PC. The test source is the same for both targets: only the output is different. The file <code>Platform.h</code> prints through <code>printf</code> on the PC and through <em>semihosting</em> (a request to the simulator or to the debugger) on the target, and the exit code of the test says whether it passed:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Platform.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">PLATFORM_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">PLATFORM_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The same test source runs on the PC and on the target: only the output differs. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">if</span><span class="token macro property"> </span><span class="token macro property expression function" style="color:rgb(130, 170, 255)">defined</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">__arm__</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Semihost_Call</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> operation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">argument</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">register</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">int</span><span class="token plain">   r0 </span><span class="token function" style="color:rgb(130, 170, 255)">__asm__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"r0"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> operation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">register</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">r1 </span><span class="token function" style="color:rgb(130, 170, 255)">__asm__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"r1"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> argument</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        __asm__ </span><span class="token keyword" style="font-style:italic">volatile</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"bkpt 0xAB"</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"+r"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">r0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"r"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">r1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"memory"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> r0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Platform_Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token function" style="color:rgb(130, 170, 255)">Semihost_Call</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0x04</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Platform_Exit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> failures</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 0x20026: the application exited normally, 0x20023: the application failed */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token function" style="color:rgb(130, 170, 255)">Semihost_Call</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0x18</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> failures </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0x20026u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0x20023u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdio.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdlib.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Platform_Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">fputs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">stdout</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Platform_Exit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> failures</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">exit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> failures </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">tests.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Conversions.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Platform.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> failures</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name function" style="color:rgb(130, 170, 255)">CHECK</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">condition</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token macro property expression"> name</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression">                                          </span><span class="token macro property punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token macro property"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token macro property">    </span><span class="token macro property expression keyword" style="font-style:italic">do</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token macro property expression">                                                                </span><span class="token macro property punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token macro property"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token macro property">        </span><span class="token macro property expression keyword" style="font-style:italic">if</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">condition</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token macro property expression"> </span><span class="token macro property expression function" style="color:rgb(130, 170, 255)">Platform_Print</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property string" style="color:rgb(195, 232, 141)">"PASS  "</span><span class="token macro property"> </span><span class="token macro property expression">name </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"\n"</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token macro property expression">          </span><span class="token macro property punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token macro property"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token macro property">        </span><span class="token macro property expression keyword" style="font-style:italic">else</span><span class="token macro property expression">           </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token macro property expression"> </span><span class="token macro property expression function" style="color:rgb(130, 170, 255)">Platform_Print</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property string" style="color:rgb(195, 232, 141)">"FAIL  "</span><span class="token macro property"> </span><span class="token macro property expression">name </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"\n"</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token macro property expression"> failures</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">++</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token macro property expression"> </span><span class="token macro property punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token macro property"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token macro property">    </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token macro property expression"> </span><span class="token macro property expression keyword" style="font-style:italic">while</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 3 000 000 ms = 50 minutes = 3 000 000 000 us */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">CHECK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">3000000000L</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Get_Microseconds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">3000000u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"50 minutes in microseconds"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">CHECK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">5000L</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Get_Microseconds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">5u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">             </span><span class="token string" style="color:rgb(195, 232, 141)">"5 ms in microseconds"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* the byte 0xFF is received from the UART */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">CHECK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Is_HighBitSet</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">char</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token number" style="color:rgb(247, 140, 108)">0xFF</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">         </span><span class="token string" style="color:rgb(195, 232, 141)">"0xFF has the high bit set"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">CHECK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Is_HighBitSet</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">char</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token number" style="color:rgb(247, 140, 108)">0x41</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"'A' has not the high bit set"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Platform_Exit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">failures</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> failures</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>On the PC:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">PASS  50 minutes in microseconds</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">PASS  5 ms in microseconds</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">PASS  0xFF has the high bit set</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">PASS  'A' has not the high bit set</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">exit code: 0</span><br></div></code></pre></div></div>
<p>The same source, compiled with <code>arm-none-eabi-gcc</code> for the Cortex-M4 and started in QEMU:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">FAIL  50 minutes in microseconds</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">PASS  5 ms in microseconds</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">FAIL  0xFF has the high bit set</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">PASS  'A' has not the high bit set</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">exit code: 1</span><br></div></code></pre></div></div>
<p>Two bugs, and both are invisible on the PC:</p>
<ul>
<li class=""><strong><code>long</code> has a different width.</strong> On a 64-bit Linux PC a <code>long</code> has 64 bits, on a Cortex-M it has 32. <code>3 000 000 ms * 1000</code> is <code>3 000 000 000</code>, which does not fit into a signed 32-bit number (the biggest is 2 147 483 647), so the result is wrong, and in C it is also an undefined behavior.</li>
<li class=""><strong><code>char</code> has a different signedness.</strong> The C standard leaves it open whether a plain <code>char</code> is signed. On x86 it is, so <code>(char)0xFF</code> is <code>-1</code> and the check <code>receivedByte &lt; 0</code> works. On the ARM it is <em>unsigned</em>, so <code>(char)0xFF</code> is <code>255</code> and the comparison is never true. The ARM compiler even says it, and only there:</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Conversions.c:10:26: warning: comparison is always false due to limited range of data type [-Wtype-limits]</span><br></div></code></pre></div></div>
<p>Both are the question of the portable types, which is the topic of the rule 4.6 in the article about <a class="" href="https://embedbits.cz/blog/misra-c-rules-in-practice">MISRA</a>: use the types with a size and a signedness. The fixed version uses <code>uint64_t</code> for the time and <code>uint8_t</code> for the byte:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint64_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Get_Microseconds_Fixed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> milliseconds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint64_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">milliseconds </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1000u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Conversions_Is_HighBitSet_Fixed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> receivedByte</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">receivedByte </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0x80u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>and the same four checks now pass <strong>on both targets</strong>, with exit code 0 on both. The first version was not a bug of the test, and the test on the PC was not wrong: it simply tested a different program.</p>
<p>The exit code is the whole integration with the CI. The simulator terminates with the code that the firmware gives to the semihosting call, so the <code>add_test</code> of CMake (see the article about <a class="" href="https://embedbits.cz/blog/cmake-for-embedded-firmware">CMake for firmware</a>) fails when the test on the target fails:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">add_test</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token property">NAME</span><span class="token plain"> conversions_on_target</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMAND qemu-system-arm -M netduinoplus2 -nographic</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            -semihosting-config enable=on,target=native -kernel conversions_test.elf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="experiment-2-the-registers-of-a-peripheral">Experiment 2: the registers of a peripheral<a href="https://embedbits.cz/blog/firmware-in-simulator-ci#experiment-2-the-registers-of-a-peripheral" class="hash-link" aria-label="Direct link to Experiment 2: the registers of a peripheral" title="Direct link to Experiment 2: the registers of a peripheral" translate="no">​</a></h2>
<p>A simulator also models the peripherals, and then the code that is closest to the hardware can run too. This is a firmware that sends a text through the USART1 of an STM32F4, written on the register level with the real addresses (no library, no startup beyond the code from the article about <a class="" href="https://embedbits.cz/blog/before-main-startup-linker">what happens before <code>main()</code></a>):</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">uart.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* STM32F4: RCC and USART1 registers, the same addresses as on the real chip */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">RCC_APB2ENR</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0x40023844u</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">USART1_SR</span><span class="token macro property">    </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0x40011000u</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">USART1_DR</span><span class="token macro property">    </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0x40011004u</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">USART1_CR1</span><span class="token macro property">   </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression keyword" style="font-style:italic">volatile</span><span class="token macro property expression"> </span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0x4001100Cu</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">RCC_APB2ENR_USART1EN</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">1u</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">4</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">USART_CR1_UE</span><span class="token macro property">          </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">1u</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">13</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">USART_CR1_TE</span><span class="token macro property">          </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">1u</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">3</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">USART_SR_TXE</span><span class="token macro property">          </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">1u</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">7</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token char" style="color:rgb(130, 170, 255)">'\0'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">USART1_SR </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> USART_SR_TXE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* wait until the data register is empty */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        USART1_DR </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">unsigned</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    RCC_APB2ENR </span><span class="token operator" style="color:rgb(137, 221, 255)">|=</span><span class="token plain"> RCC_APB2ENR_USART1EN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* clock of the peripheral */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    USART1_CR1  </span><span class="token operator" style="color:rgb(137, 221, 255)">|=</span><span class="token plain"> USART_CR1_UE </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> USART_CR1_TE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">           </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* enable the USART and its transmitter */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"hello from the register level\r\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">hello from the register level</span><br></div></code></pre></div></div>
<p>The text is in the terminal of the simulator: the firmware switched on the clock of the peripheral in the RCC, enabled the USART and its transmitter, waited for the flag <code>TXE</code> and wrote the data register, exactly as it would on the board, and the model of the USART passed the byte to the serial port. It is a test of a driver against a model of the register interface. If a driver waits for a flag that never comes, the test finds it by a timeout, and not at the desk with an oscilloscope.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-simulator-does-not-tell-you">What the simulator does not tell you<a href="https://embedbits.cz/blog/firmware-in-simulator-ci#what-the-simulator-does-not-tell-you" class="hash-link" aria-label="Direct link to What the simulator does not tell you" title="Direct link to What the simulator does not tell you" translate="no">​</a></h2>
<p>A simulator is a <em>model</em>, and every model has a boundary. A few that I met in the experiments of this series:</p>
<ul>
<li class=""><strong>The timing is not real.</strong> QEMU runs the instructions as fast as the PC allows and does not count the cycles of the real core. A test that must prove "the interrupt is served within 5 microseconds" cannot be done in it.</li>
<li class=""><strong>The interrupts arrive in other places than on the MCU.</strong> In the article about <a class="" href="https://embedbits.cz/blog/interrupts-and-main-shared-data">interrupts</a> the lost update of a shared counter did not appear in QEMU in 200 000 tries, because QEMU delivers an interrupt between blocks of the translated code. The real MCU can interrupt after every instruction. A simulator does not prove the absence of a race.</li>
<li class=""><strong>Only the modeled peripherals exist.</strong> The model of the STM32F405 has a USART, but another chip may have a peripheral that the model does not have, or has it in a simplified form: the registers are there, the analog part is not.</li>
<li class=""><strong>The electrical world is missing:</strong> a bounce of a contact, the noise on an ADC input, a voltage drop. Everything that comes from the outside is what you put into the model.</li>
</ul>
<p>So the simulator replaces neither the unit tests (they are faster and test the logic in isolation) nor the hardware tests (they test the reality). It finds the things between: the compiler of the target, the types, the startup, the memory map, the driver against a register model, and it does it in a few seconds on every commit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="renode">Renode<a href="https://embedbits.cz/blog/firmware-in-simulator-ci#renode" class="hash-link" aria-label="Direct link to Renode" title="Direct link to Renode" translate="no">​</a></h2>
<p>The platform has an artifact for <strong>Renode</strong>, Antmicro's open-source simulation and virtual development framework, shipped together with <code>renode-test</code>, its Robot Framework based test runner, which is used for the integration tests of simulated firmware. I did not run it for this article (the release could not be downloaded in my environment), so I only repeat what its documentation says, and I do not compare it with QEMU. The structure of such a test is the same as above: the real ELF, a model of the hardware, a verdict and an exit code for the CI.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-checklist">A checklist<a href="https://embedbits.cz/blog/firmware-in-simulator-ci#a-checklist" class="hash-link" aria-label="Direct link to A checklist" title="Direct link to A checklist" translate="no">​</a></h2>
<ol>
<li class="">Build the test for the <strong>target</strong>, with the compiler of the target, and run it in a simulator, in addition to the PC.</li>
<li class="">Use one test source for both, with a thin layer (<code>Platform.h</code>) for the output and the exit.</li>
<li class="">The exit code of the simulator is the result of the test, so the CI needs nothing more.</li>
<li class="">Use the types with a size and a signedness (<code>uint32_t</code>, <code>uint8_t</code>) and the warnings of the target compiler: the second bug above (the <code>char</code>) would be found by <code>-Wtype-limits</code>, if anyone looked at the output of the ARM build.</li>
<li class="">Write down what the simulator cannot prove (the timing, the races, the analog world) and leave it to the hardware tests.</li>
</ol>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="Testing" term="Testing"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Reproducible builds: pin the tools, pin the sources, remove the clock]]></title>
        <id>https://embedbits.cz/blog/reproducible-builds-embedded</id>
        <link href="https://embedbits.cz/blog/reproducible-builds-embedded"/>
        <updated>2026-10-07T14:00:00.000Z</updated>
        <summary type="html"><![CDATA[A customer calls about a firmware that you delivered fourteen months ago. You check out the tag, build it, flash it and the bug is not there. Is the bug gone, or is it a different firmware? If your build is not reproducible, you cannot tell. Nobody can tell, because the binary that you have just built differs from the delivered one in ways that you can neither see nor explain: another version of the compiler, a library that was updated on the PC, the path of the folder, the time of the day.]]></summary>
        <content type="html"><![CDATA[<p>A customer calls about a firmware that you delivered fourteen months ago. You check out the tag, build it, flash it and the bug is not there. Is the bug gone, or is it a different firmware? If your build is not <strong>reproducible</strong>, you cannot tell. Nobody can tell, because the binary that you have just built differs from the delivered one in ways that you can neither see nor explain: another version of the compiler, a library that was updated on the PC, the path of the folder, the time of the day.</p>
<p>A reproducible build has a simple definition: <strong>the same inputs give the same bytes</strong>. This article shows what the inputs of a firmware build are, how the Embedbits platform pins them (the Artifacts Handler), and an experiment that I did: two builds of the same source, in two folders at two different times, give two different binaries. Then three changes later they give the same one, to the last bit.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-inputs-of-a-build">The inputs of a build<a href="https://embedbits.cz/blog/reproducible-builds-embedded#the-inputs-of-a-build" class="hash-link" aria-label="Direct link to The inputs of a build" title="Direct link to The inputs of a build" translate="no">​</a></h2>
<p>A build is a function. What goes into it?</p>



































<table><thead><tr><th>Input</th><th>Where it comes from</th><th>How to pin it</th></tr></thead><tbody><tr><td><strong>The source</strong></td><td>Git</td><td>a tag or a commit, the submodules pinned by their commits</td></tr><tr><td><strong>The tools</strong> (compiler, linker, Ninja, Doxygen)</td><td>installed on the PC, or fetched</td><td>exact versions, from one source</td></tr><tr><td><strong>The build description</strong> (flags, linker script)</td><td>CMake files</td><td>in the repository, nothing set by hand</td></tr><tr><td><strong>The platform scripts</strong></td><td>the EmBi_Platform submodule</td><td>the submodule commit, updated by the Updater, deliberately</td></tr><tr><td><strong>The environment</strong></td><td>the PC</td><td>nothing in the output should depend on it: the path, the time, the user name</td></tr></tbody></table>
<p>The first, third and fourth are in Git, so they are pinned by design. The tools and the environment are where a build usually breaks, and each of them has its own answer.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-tools-the-artifacts-handler">The tools: the Artifacts Handler<a href="https://embedbits.cz/blog/reproducible-builds-embedded#the-tools-the-artifacts-handler" class="hash-link" aria-label="Direct link to The tools: the Artifacts Handler" title="Direct link to The tools: the Artifacts Handler" translate="no">​</a></h2>
<p>"Install GCC 13.2 and Ninja 1.12" in a README is a sentence that nobody follows to the letter. The platform solves it by making the tools a part of the project. The Artifacts Handler is a CMake script that reads a list of the tools and their versions from a file, <code>ArtifactsConfig.txt</code>, and prepares them. Its documentation says that the only software that the user needs is Git and CMake, and that every other component of the build is delivered by the handler. In steps:</p>
<ol>
<li class=""><strong>Clone</strong> the root repository of the artifacts (without the submodules, to save the traffic).</li>
<li class=""><strong>Locate</strong> the artifact in it (every tool is a submodule, the names are compared without the case).</li>
<li class=""><strong>Check out</strong> the requested version (a shallow clone, <code>--depth=1</code>). The releases are tagged by the version and the operating system (<code>Win</code>, <code>Unix</code>, <code>DarwinARM</code>).</li>
<li class=""><strong>Install</strong> it: unpack the archive into the cache folder.</li>
<li class=""><strong>Initialize</strong> it: in most cases it puts the folder of the tool at the <em>beginning</em> of the <code>PATH</code>, so the project tool wins over any tool installed in the system.</li>
</ol>
<p>The configuration has one line for each tool, <code>name;version;handler version</code>, for example the lines from the platform documentation:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">ninja;1.12.1;1</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">gcc-arm-none-eabi;13.2.rel1;2</span><br></div></code></pre></div></div>
<p>The first number is the version of the tool itself (the <em>binary</em>), the second one is the version of the handler script of that artifact (it can change independently, for example when the way of setting the <code>PATH</code> is fixed). The cache has one folder per tool and per version, so several versions live side by side and a project that needs the older one does not disturb the project that needs the newer.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-not-latest">Why not <code>latest</code><a href="https://embedbits.cz/blog/reproducible-builds-embedded#why-not-latest" class="hash-link" aria-label="Direct link to why-not-latest" title="Direct link to why-not-latest" translate="no">​</a></h3>
<p>The handler also accepts <code>latest</code> instead of a number. It is comfortable and it breaks the whole idea. I ran the handler with the line <code>ninja;latest;latest</code>, and it printed what it resolved it to on 5 October 2026:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">-- Processing artifact ninja with Bin version latest and Core version latest.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">-- The version 1.0.0 of artifacts Core part will be used.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">-- The version 1.13.2 of artifacts Bin part will be used.</span><br></div></code></pre></div></div>
<p>(The run stopped at the download of the release, because my environment cannot reach the GitHub API, but the resolution happened.) <code>latest</code> is a <strong>moving target</strong>: with the documentation saying that the list of the versions is downloaded once a day, the same file gives the 1.13.2 today and something else after the next release. A build that is correct today can be a different build tomorrow, and nothing in your repository says so. The rule is therefore simple: <strong><code>latest</code> is for trying a new version, and a released project pins every number.</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-other-settings-that-help">The other settings that help<a href="https://embedbits.cz/blog/reproducible-builds-embedded#the-other-settings-that-help" class="hash-link" aria-label="Direct link to The other settings that help" title="Direct link to The other settings that help" translate="no">​</a></h3>
<ul>
<li class=""><strong>An offline mode</strong> (<code>-DOFFLINE_MODE=true</code>): only the local cache is checked and nothing is downloaded. It is the way to prove that the build does not depend on the network, and the way to build in a place where the network is not.</li>
<li class=""><strong>The location of the cache</strong> (<code>ARTIFACTS_HANDLER_CACHE_PATH</code>) and <strong>of the root repository</strong> (<code>ARTIFACTS_HANDLER_ROOT_REPO_URL</code>) can be set in the configuration file, in the environment or on the command line. A company can run its own mirror of the artifacts, so the build does not depend on a public server either.</li>
<li class=""><strong>A checksum.</strong> Each release of an artifact is published with a SHA-256 file next to the archive, so a corrupted or exchanged file is not accepted silently.</li>
</ul>
<p>The tools are the first half of the answer. The second half is something that you can check yourself, with the command below.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-environment-an-experiment">The environment: an experiment<a href="https://embedbits.cz/blog/reproducible-builds-embedded#the-environment-an-experiment" class="hash-link" aria-label="Direct link to The environment: an experiment" title="Direct link to The environment: an experiment" translate="no">​</a></h2>
<p>I took the example project from the article about <a class="" href="https://embedbits.cz/blog/cmake-for-embedded-firmware">CMake</a> and added a file that most firmwares have in some form: the <strong>build information</strong>. It stores the time of the build and the path of the source file, because someone once wanted to see "when was this built" in the debugger:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> buildFile</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">__FILE__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> buildTime</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">__DATE__</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">" "</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">__TIME__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>Then I built the same source twice: in two different folders (<code>a</code> and <code>b</code>), the second one three seconds later. The <code>strings</code> command applied to the two binaries shows what is inside:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Oct  5 2026 15:46:02</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">/tmp/.../repro/a/Application/BuildInfo.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">---</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Oct  5 2026 15:46:05</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">/tmp/.../repro/b/Application/BuildInfo.c</span><br></div></code></pre></div></div>
<p>and the SHA-256 of the two <code>firmware.bin</code> files differ:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">f2366319462b6fee...</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">d634c24c3c431799...</span><br></div></code></pre></div></div>
<p>Two builds of one source, two different binaries. The time is obvious, but the <strong>path</strong> is the one that people forget: <code>__FILE__</code> (and also <code>assert()</code> and the debug information) writes the full path of the file into the program, and the path is different on the PC of every developer and in every CI job. A binary built in <code>/home/anna/project</code> and the same one built in <code>/builds/job-4711/project</code> are two different files.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="three-changes">Three changes<a href="https://embedbits.cz/blog/reproducible-builds-embedded#three-changes" class="hash-link" aria-label="Direct link to Three changes" title="Direct link to Three changes" translate="no">​</a></h3>
<p><strong>1. Remove the clock.</strong> The macros <code>__DATE__</code> and <code>__TIME__</code> have no place in a firmware that has to be reproducible. The compiler can enforce it, so nobody adds them back by accident:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">BuildInfo.c:5:26: error: macro "__DATE__" might prevent reproducible builds [-Werror=date-time]</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">BuildInfo.c:5:39: error: macro "__TIME__" might prevent reproducible builds [-Werror=date-time]</span><br></div></code></pre></div></div>
<p><strong>2. The version is an input.</strong> If you want to know "what is this firmware", the build gets the answer from the outside: a version, a tag or a commit hash that the build system passes as a definition. The same source has the same version, so the same bytes:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">BUILD_VERSION</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">BUILD_VERSION</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"unknown"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> buildVersion</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUILD_VERSION</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p><strong>3. Remove the paths.</strong> The option <code>-ffile-prefix-map=OLD=NEW</code> replaces the prefix of every path that GCC puts into the output (<code>__FILE__</code>, the debug information, the assertions). The source folder of the project is replaced by a dot:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">CMakeLists.txt (a part)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># The version of the firmware is an input of the build, not the time of the build.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">FIRMWARE_VERSION</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"1.2.3"</span><span class="token plain"> </span><span class="token variable" style="color:rgb(191, 199, 213)">CACHE</span><span class="token plain"> STRING </span><span class="token string" style="color:rgb(195, 232, 141)">"Version of the firmware"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_compile_definitions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">BUILD_VERSION</span><span class="token plain">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string interpolation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token string interpolation variable" style="color:rgb(191, 199, 213)">FIRMWARE_VERSION</span><span class="token string interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># No clock in the binary, and no path of this PC in it.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_compile_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">MCU_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">WARNING_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">BUILD_OPTIONS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                    -Wdate-time -Werror=date-time</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                    -ffile-prefix-map=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">=.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>With these three, the same check gives:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">first : 1bedc9d2b1d78452a77fa3440851d5ed3d9f6568d96edd4c4a18be3b828dc313</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">second: 1bedc9d2b1d78452a77fa3440851d5ed3d9f6568d96edd4c4a18be3b828dc313</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">REPRODUCIBLE</span><br></div></code></pre></div></div>
<p>The <code>.bin</code> is identical, and so is the <code>.elf</code>, in the release (<code>-Os -g0</code>) and also in the debug build (<code>-Og -g3</code>), whose debug information is full of paths. With <code>-ffile-prefix-map</code> the <code>strings</code> of the binary shows <code>./Application/BuildInfo.c</code> and the version <code>1.2.3</code>, and nothing about the PC that built it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-test-that-never-gets-old">A test that never gets old<a href="https://embedbits.cz/blog/reproducible-builds-embedded#a-test-that-never-gets-old" class="hash-link" aria-label="Direct link to A test that never gets old" title="Direct link to A test that never gets old" translate="no">​</a></h2>
<p>It is not enough to make a build reproducible once, because the first <code>__TIME__</code> that somebody adds destroys it. So make it a <strong>test</strong>: build the source twice and compare. This is the script that I used for the numbers above; it copies the project into two folders, builds both with a pause between and compares the SHA-256:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">check-reproducible.sh</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token shebang important">#!/usr/bin/env bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Builds the same source twice, in two different folders, and compares the firmware.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-euo</span><span class="token plain"> pipefail</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">source_dir</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$(</span><span class="token string variable builtin class-name" style="color:rgb(255, 203, 107)">cd</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">$1</span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable builtin class-name" style="color:rgb(255, 203, 107)">pwd</span><span class="token string variable" style="color:rgb(191, 199, 213)">)</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">config</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">${2</span><span class="token string variable operator" style="color:rgb(137, 221, 255)">:-</span><span class="token string variable" style="color:rgb(191, 199, 213)">Release}</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">work</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$(</span><span class="token string variable" style="color:rgb(191, 199, 213)">mktemp </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-d</span><span class="token string variable" style="color:rgb(191, 199, 213)">)</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token for-or-select variable" style="color:rgb(191, 199, 213)">copy</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> first second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">cp</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-r</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$source_dir</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">/</span><span class="token string variable" style="color:rgb(191, 199, 213)">$copy</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-rf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">/</span><span class="token string variable" style="color:rgb(191, 199, 213)">$copy</span><span class="token string" style="color:rgb(195, 232, 141)">/build"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-S</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">/</span><span class="token string variable" style="color:rgb(191, 199, 213)">$copy</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-B</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">/</span><span class="token string variable" style="color:rgb(191, 199, 213)">$copy</span><span class="token string" style="color:rgb(195, 232, 141)">/build"</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-G</span><span class="token plain"> Ninja </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-DCMAKE_TOOLCHAIN_FILE</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">cmake/arm-none-eabi.cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-DCMAKE_BUILD_TYPE</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$config</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> /dev/null</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">--build</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">/</span><span class="token string variable" style="color:rgb(191, 199, 213)">$copy</span><span class="token string" style="color:rgb(195, 232, 141)">/build"</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> /dev/null</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">sleep</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token plain">                                    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># the second build is later and is in another folder</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">first</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$(</span><span class="token string variable" style="color:rgb(191, 199, 213)">sha256sum </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string variable string" style="color:rgb(195, 232, 141)">/first/build/firmware.bin"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable operator" style="color:rgb(137, 221, 255)">|</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable function" style="color:rgb(130, 170, 255)">cut</span><span class="token string variable" style="color:rgb(191, 199, 213)"> -d</span><span class="token string variable string" style="color:rgb(195, 232, 141)">' '</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-f1</span><span class="token string variable" style="color:rgb(191, 199, 213)">)</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">second</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$(</span><span class="token string variable" style="color:rgb(191, 199, 213)">sha256sum </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string variable string" style="color:rgb(195, 232, 141)">/second/build/firmware.bin"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable operator" style="color:rgb(137, 221, 255)">|</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable function" style="color:rgb(130, 170, 255)">cut</span><span class="token string variable" style="color:rgb(191, 199, 213)"> -d</span><span class="token string variable string" style="color:rgb(195, 232, 141)">' '</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-f1</span><span class="token string variable" style="color:rgb(191, 199, 213)">)</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"first : </span><span class="token string variable" style="color:rgb(191, 199, 213)">$first</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"second: </span><span class="token string variable" style="color:rgb(191, 199, 213)">$second</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$first</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$second</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">then</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"REPRODUCIBLE"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"NOT REPRODUCIBLE"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">exit</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">fi</span><br></div></code></pre></div></div>
<p>Run in the CI on every merge, it is the guard. I used it on the broken version of the build information too, to be sure that it can fail, and it did (<code>NOT REPRODUCIBLE</code>, exit code 1, two different hashes). A test that has never failed is a test that you do not know.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-else-breaks-a-reproducible-build">What else breaks a reproducible build<a href="https://embedbits.cz/blog/reproducible-builds-embedded#what-else-breaks-a-reproducible-build" class="hash-link" aria-label="Direct link to What else breaks a reproducible build" title="Direct link to What else breaks a reproducible build" translate="no">​</a></h2>
<p>I tested the three things above. The following are the other well-known sources of the trouble that you should keep in mind (I did not need them in the example, so I only name them):</p>
<ul>
<li class=""><strong>The order of files</strong> that comes from a <code>file(GLOB ...)</code> or from a directory listing. The sources should be listed explicitly, as in the CMake files of the platform modules.</li>
<li class=""><strong>A timestamp in an archive</strong> (a static library made by <code>ar</code>). The modern versions of the tools have a deterministic mode, but an old toolchain may not.</li>
<li class=""><strong>Generated code.</strong> The mocks and the runners of the unit tests, or the linker script generated for an MCU, have to be generated the same way from the same inputs. Sorting and no timestamps in the output are the rules.</li>
<li class=""><strong>The compiler itself.</strong> The same version of the same compiler from two sources (a distribution package and an archive of the vendor) can differ in the libraries it links. That is the reason to take the compiler from one place, which is the whole point of the artifacts.</li>
<li class=""><strong>The build with a different number of threads.</strong> A correct build system gives the same result with <code>-j1</code> and <code>-j16</code>, and a test of that is a cheap addition to the one above.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-checklist">A checklist<a href="https://embedbits.cz/blog/reproducible-builds-embedded#a-checklist" class="hash-link" aria-label="Direct link to A checklist" title="Direct link to A checklist" translate="no">​</a></h2>
<ol>
<li class="">Every tool is pinned to an exact version in <code>ArtifactsConfig.txt</code>. No <code>latest</code> in a release.</li>
<li class="">The submodules (the BSP, the platform) are pinned by commits, and the update is a visible commit.</li>
<li class="">Nothing in the firmware depends on the time or the path: <code>-Werror=date-time</code>, <code>-ffile-prefix-map</code>.</li>
<li class="">The version is a parameter of the build, derived from a tag, and is stored in the firmware.</li>
<li class="">The CI builds twice and compares. It also builds offline, from the cache, once in a while.</li>
<li class="">The delivered binary is stored together with its SHA-256 and the tag, so "is it the same file" has an answer without a rebuild.</li>
</ol>
<p>The reward is a sentence that you will use at the telephone with the customer: <em>"I have built exactly your firmware, and the bug is (not) in it."</em></p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="CMake" term="CMake"/>
        <category label="Architecture" term="Architecture"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Designing a peripheral API: eight decisions behind the Gpio module]]></title>
        <id>https://embedbits.cz/blog/designing-peripheral-api-gpio</id>
        <link href="https://embedbits.cz/blog/designing-peripheral-api-gpio"/>
        <updated>2026-10-07T10:00:00.000Z</updated>
        <summary type="html"><![CDATA[The GPIO is the simplest peripheral of a microcontroller how a pin is named, what a function returns, where the polarity of an LED lives. The MCAL module Gpio of the Embedbits BSP is a real example with real answers, and I will go through them one by one, with the alternatives and the price.]]></summary>
        <content type="html"><![CDATA[<p>The GPIO is the simplest peripheral of a microcontroller: a pin is high or low. That is exactly why it is a good subject for an article about the <strong>design of an interface</strong>. There is no hardware complexity to hide behind, and every decision is a choice of the designer: how a pin is named, what a function returns, where the polarity of an LED lives. The MCAL module <code>Gpio</code> of the Embedbits BSP is a real example with real answers, and I will go through them one by one, with the alternatives and the price.</p>
<p>The code from the module is quoted from the STM32H5 branch of <a href="https://github.com/Embedbits/Bsp-Mcal-Gpio" target="_blank" rel="noopener noreferrer" class="">Bsp-Mcal-Gpio</a>. The examples that use it were compiled and run against the <strong>real</strong> <code>Gpio_Port.h</code> and <code>Gpio_Types.h</code>, with a small fake of the implementation, so that the API could be tried on a PC.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-whole-interface-on-one-screen">The whole interface on one screen<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#the-whole-interface-on-one-screen" class="hash-link" aria-label="Direct link to The whole interface on one screen" title="Direct link to The whole interface on one screen" translate="no">​</a></h2>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_ModuleVersion_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Get_ModuleVersion</span><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Init</span><span class="token plain">               </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_Config_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">gpioConfig </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">                 </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Deinit</span><span class="token plain">             </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">                 </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Task</span><span class="token plain">               </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PortActive</span><span class="token plain">     </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinMode</span><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain"> pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinMode_t</span><span class="token plain"> pinType </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Get_PinMode</span><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain"> pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinMode_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> pinType </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ... speed, output type, alternate function and pull in the same pairs ... */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Toggle_PinLevel</span><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain"> pinId </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinLevel</span><span class="token plain">       </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain"> pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinLevel_t</span><span class="token plain"> pinLevel </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Get_PinLevel</span><span class="token plain">       </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain"> pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinLevel_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> pinLevel </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinStateActive</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain"> pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinLevel_t</span><span class="token plain"> pinActiveLevel </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_RequestState_t</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinStateInactive</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain"> pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinLevel_t</span><span class="token plain"> pinActiveLevel </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>Every decision below can be read from this list.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-a-pin-is-a-pair-of-identifiers-not-a-vendor-macro">1. A pin is a pair of identifiers, not a vendor macro<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#1-a-pin-is-a-pair-of-identifiers-not-a-vendor-macro" class="hash-link" aria-label="Direct link to 1. A pin is a pair of identifiers, not a vendor macro" title="Direct link to 1. A pin is a pair of identifiers, not a vendor macro" translate="no">​</a></h2>
<p>The vendor drivers address a pin with a pointer to a register block and a bit mask: <code>LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5)</code>. The MCAL takes two enumerations instead, <code>gpio_PortId_t</code> and <code>gpio_PinId_t</code>:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> GPIO_PORT_A</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_ID_5</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_LEVEL_HIGH </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p><strong>Why:</strong> the code above the MCAL does not need any vendor header, it does not know what <code>GPIOA</code> is (the address of a register block of the vendor), and an identifier can be range-checked, as an arbitrary pointer cannot. Each enumeration ends with a counter (<code>GPIO_PORT_CNT</code>, <code>GPIO_PIN_ID_CNT</code>), which is the upper limit for the check at the beginning of a function.</p>
<p><strong>The price:</strong> a table that translates the identifier to the register block (in <code>Gpio.c</code>, one line per port) and one more indirection. The table also solves a problem of its own: the MCUs of a family have a different number of ports, so the entries are wrapped in <code>#if defined(GPIOK)</code> (see the article about <a class="" href="https://embedbits.cz/blog/bsp-stm32-families-git-branches">the families</a>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-every-function-that-can-fail-returns-a-state-and-the-results-go-out-through-a-pointer">2. Every function that can fail returns a state, and the results go out through a pointer<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#2-every-function-that-can-fail-returns-a-state-and-the-results-go-out-through-a-pointer" class="hash-link" aria-label="Direct link to 2. Every function that can fail returns a state, and the results go out through a pointer" title="Direct link to 2. Every function that can fail returns a state, and the results go out through a pointer" translate="no">​</a></h2>
<p>All functions except <code>Deinit</code>, <code>Task</code> and the version getter return <code>gpio_RequestState_t</code>, and the getters deliver the value through a pointer parameter:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinLevel_t</span><span class="token plain"> level </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_LEVEL_LOW</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_REQUEST_OK </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Get_PinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_PORT_C</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_ID_13</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">level</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* level is valid here */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><strong>Why:</strong> the return value of a getter cannot carry the value <em>and</em> the information that the value is not valid (<code>GPIO_PIN_LEVEL_LOW</code> is a valid level, so a returned <code>0</code> is ambiguous). With the state in the return value and the data in the parameter, an invalid port, an invalid pin or a <code>NULL</code> pointer is a visible error and not a silently wrong level. The <code>* const</code> in the signature says that the function does not change the pointer, only the data behind it.</p>
<p><strong>The price:</strong> two lines instead of one at every use. And the state has two values (<code>GPIO_REQUEST_OK</code>, <code>GPIO_REQUEST_ERROR</code>), so the caller knows <em>that</em> it failed and not <em>why</em>. For a GPIO it is enough, because there are only a few reasons (an invalid identifier, a <code>NULL</code>), and all of them are programming errors. For a peripheral with a real failure (a timeout of the I2C, a bus error), the caller needs more, and a richer enumeration is the usual answer.</p>
<p>The rule from the article about <a class="" href="https://embedbits.cz/blog/misra-c-rules-in-practice">MISRA</a> that applies is 17.7 (the returned value is used): here the interface makes it easy to follow, because every function that can fail tells it through the value that you have to look at.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-a-pin-is-configured-by-data-not-by-a-sequence-of-calls">3. A pin is configured by data, not by a sequence of calls<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#3-a-pin-is-configured-by-data-not-by-a-sequence-of-calls" class="hash-link" aria-label="Direct link to 3. A pin is configured by data, not by a sequence of calls" title="Direct link to 3. A pin is configured by data, not by a sequence of calls" translate="no">​</a></h2>
<p>There is a configuration structure with everything that describes a pin, and one function that applies it:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain">        PortId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">         </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; GPIO port identification       */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain">         PinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; GPIO pin identification        */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinMode_t</span><span class="token plain">       PinMode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; GPIO pin type                  */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinPullCfg_t</span><span class="token plain">    PinPull</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; GPIO pin pull configuration    */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinSpeed_t</span><span class="token plain">      PinSpeed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; GPIO output speed              */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinOutputType_t</span><span class="token plain"> PinOutType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; GPIO output style              */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_AltFunction_t</span><span class="token plain">   PinAltFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Alternate function used by pin */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinLevel_t</span><span class="token plain">      PinActiveLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Pin level in active state      */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_Config_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p><strong>Why:</strong> the knowledge about the board then lives in a <strong>table</strong>, and the code that applies it is the same for every board. Look at the example that I compiled and ran: the board is two entries, and the initialization is a loop.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">board.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Gpio_Port.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The board is data: which pin is what, and what "active" means for it. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> BOARD_IO_LED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> BOARD_IO_BUTTON</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> BOARD_IO_CNT </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">boardIo_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_Config_t</span><span class="token plain"> boardPins</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BOARD_IO_CNT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BOARD_IO_LED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PortId </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PORT_A</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinId </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_ID_5</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinMode </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_MODE_OUTPUT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinPull </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_PULL_NONE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinSpeed </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_SPEED_LOW</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinOutType </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_OUTPUT_PUSHPULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinAltFunction </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_ALT_FUNC_CNT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinActiveLevel </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_LEVEL_LOW        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* this LED is connected to the supply: low = on */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BOARD_IO_BUTTON</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PortId </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PORT_C</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinId </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_ID_13</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinMode </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_MODE_INPUT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinPull </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_PULL_NONE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinSpeed </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_SPEED_LOW</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinOutType </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_OUTPUT_PUSHPULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinAltFunction </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_ALT_FUNC_CNT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">PinActiveLevel </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_LEVEL_HIGH</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Board_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    bool isOk </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">BOARD_IO_CNT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_REQUEST_OK </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">boardPins</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            isOk </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> isOk</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Board_Set_Led</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool isOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_Config_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">led </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">boardPins</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BOARD_IO_LED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_REQUEST_OK </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">isOn</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinStateActive</span><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">led</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">PortId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> led</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">PinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> led</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">PinActiveLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinStateInactive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">led</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">PortId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> led</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">PinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> led</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">PinActiveLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Because the table is data, a new revision of the PCB changes a line in the table and nothing in the code. In the Embedbits architecture it is the job of the HAL layer: it holds the tables and uses the MCAL to apply them.</p>
<p><strong>The price:</strong> the structure has eight fields and every entry has to fill all of them (the designated initializers make it readable, and a field that is left out is zero, which is not always a sensible value). That is why a <code>Get_DefaultConfig</code> function, which some other modules have, is a useful companion.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-the-polarity-of-a-signal-is-a-property-of-the-pin-not-of-the-code">4. The polarity of a signal is a property of the pin, not of the code<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#4-the-polarity-of-a-signal-is-a-property-of-the-pin-not-of-the-code" class="hash-link" aria-label="Direct link to 4. The polarity of a signal is a property of the pin, not of the code" title="Direct link to 4. The polarity of a signal is a property of the pin, not of the code" translate="no">​</a></h2>
<p>The structure has the field <code>PinActiveLevel</code>, and there are the functions <code>Gpio_Set_PinStateActive()</code> and <code>Gpio_Set_PinStateInactive()</code>, which take the polarity as a parameter. The reason is a plain fact of electronics: an LED can be connected to the ground (it lights up with a <strong>high</strong> level) or to the supply (it lights up with a <strong>low</strong> level), and a chip-select signal is usually <em>active low</em>. If the code says <code>Gpio_Set_PinLevel(..., HIGH)</code> for "LED on", it is right for one board and wrong for the next.</p>
<p>With the polarity in the table, the application says "on" and the table says what that means. In the example above the LED is connected to the supply, so <code>PinActiveLevel</code> is <code>GPIO_PIN_LEVEL_LOW</code>, and the test confirms what the pin does:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">after Board_Init():      the pin is high (the LED is off)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">after Board_Set_Led(1):  the pin is low  (the LED is on)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-the-enumerations-are-the-vendor-constants">5. The enumerations are the vendor constants<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#5-the-enumerations-are-the-vendor-constants" class="hash-link" aria-label="Direct link to 5. The enumerations are the vendor constants" title="Direct link to 5. The enumerations are the vendor constants" translate="no">​</a></h2>
<p>The types do not invent their own numbers, they are the numbers of the vendor driver:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    GPIO_PIN_MODE_INPUT     </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> LL_GPIO_MODE_INPUT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Select input mode              */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    GPIO_PIN_MODE_OUTPUT    </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> LL_GPIO_MODE_OUTPUT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Select output mode             */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    GPIO_PIN_MODE_ALTERNATE </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> LL_GPIO_MODE_ALTERNATE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Select alternate function mode */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    GPIO_PIN_MODE_ANALOG    </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> LL_GPIO_MODE_ANALOG     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Select analog mode             */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinMode_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p><strong>Why:</strong> the conversion from the type of the MCAL to the value that the LL function wants is <strong>free</strong>: there is no <code>switch</code>, no table and no way to make a typing mistake in the translation. The values of the constants differ from a family to a family, and that is hidden in the one <code>#include</code> of the RAL port (the family-specific <code>Stm32_gpio.h</code>).</p>
<p><strong>The price:</strong> <code>Gpio_Types.h</code>, a public header, includes the header of the RAL, so the vendor constants leak into the headers that the users of the module see. The alternative is the type with its own values and a translation table in the <code>.c</code> file, which costs code and a place for a bug, but keeps the vendor out of the public headers. The decision is a compromise, and it is good to know that it is one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-the-same-lifecycle-as-every-other-module">6. The same lifecycle as every other module<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#6-the-same-lifecycle-as-every-other-module" class="hash-link" aria-label="Direct link to 6. The same lifecycle as every other module" title="Direct link to 6. The same lifecycle as every other module" translate="no">​</a></h2>
<p><code>Gpio_Get_ModuleVersion()</code>, <code>Gpio_Init()</code>, <code>Gpio_Deinit()</code> and <code>Gpio_Task()</code> come from the template that every module starts with (see the article about the <a class="" href="https://embedbits.cz/blog/file-organization-embedded-c">file organization</a>). The difference is in the one place where it makes sense: <code>Gpio_Init()</code> is not <code>void</code>, it takes <strong>a pin configuration</strong>. A GPIO module does not know the board, so "initialize the module" has no meaning without the question "which pin?". A uniform lifecycle that is bent where the nature of the module requires it is better than a lifecycle that is forced on a module where it does not fit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-the-order-of-the-steps-is-a-part-of-the-interface">7. The order of the steps is a part of the interface<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#7-the-order-of-the-steps-is-a-part-of-the-interface" class="hash-link" aria-label="Direct link to 7. The order of the steps is a part of the interface" title="Direct link to 7. The order of the steps is a part of the interface" translate="no">​</a></h2>
<p>Look at the comment of <code>Gpio_Init()</code>:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Activates the port clock and configures the pin. Output level (inactive state),</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * output type, speed, pull and alternate function are configured before the pin</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * mode, so an output pin starts directly with its inactive level (no glitch).</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Configuration stops at the first failed step.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><br></div></code></pre></div></div>
<p>The pin mode, which is the step that actually <strong>connects the output driver to the pad</strong>, is the last. If the mode were first, the pin would for a moment drive the level that the output register had after the reset (usually low), and then jump to the right one: a pulse on a line that may be a chip-select, a reset of another chip or the gate of a transistor. Such a glitch is invisible in a debugger and visible on an oscilloscope. It is a good example of a rule for API design: <strong>when the order of the steps matters for the hardware, the function that does them should own the order</strong>, so the user cannot get it wrong.</p>
<p>The second sentence of the comment, "stops at the first failed step", is also a design decision: the function does not try to continue after an error, and it returns the state of the failing step.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="8-a-wrong-argument-is-an-error-that-the-caller-can-see-not-a-crash">8. A wrong argument is an error that the caller can see, not a crash<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#8-a-wrong-argument-is-an-error-that-the-caller-can-see-not-a-crash" class="hash-link" aria-label="Direct link to 8. A wrong argument is an error that the caller can see, not a crash" title="Direct link to 8. A wrong argument is an error that the caller can see, not a crash" translate="no">​</a></h2>
<p>The functions check their arguments, and the answer is the state:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">assert</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_REQUEST_ERROR </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_NULL_PTR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">assert</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_REQUEST_ERROR </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Get_PinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_PORT_CNT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_ID_0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">level</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">assert</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_REQUEST_ERROR </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_PORT_A</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_ID_CNT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_LEVEL_HIGH</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>(This is the test of my fake, but the real <code>Gpio_Init()</code> does the same for the <code>NULL</code>: the whole body is inside <code>if( GPIO_NULL_PTR != gpioConfig )</code>.) The <code>_CNT</code> constants have a second job here: <code>GPIO_PORT_CNT</code> is the first value that is <strong>not</strong> a valid port, so the check is a single comparison. In a firmware, there is no one to show a message to, and an <code>assert</code> that stops the program is usually the wrong answer for a production build. An error that goes up to the caller, who knows what to do (and a module on top of the MCAL that knows what is critical), is a better one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-i-would-look-at-again">What I would look at again<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#what-i-would-look-at-again" class="hash-link" aria-label="Direct link to What I would look at again" title="Direct link to What I would look at again" translate="no">​</a></h2>
<p>An honest design review always has a list, and this one has two items that come from the article about MISRA:</p>
<ul>
<li class=""><code>Gpio_Init( gpio_Config_t *gpioConfig )</code> only <strong>reads</strong> the structure, so the parameter could be <code>const gpio_Config_t *</code> (Rule 8.13). The signature would say that the function does not change the configuration, and the table of the board could be <code>const</code> and live in the flash instead of the RAM.</li>
<li class="">The two-valued <code>gpio_RequestState_t</code> is the same in every module (it is generated by the template). It is a simple and uniform decision that is right for the GPIO, and the modules with the real failures will sooner or later need more.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-principles-short">The principles, short<a href="https://embedbits.cz/blog/designing-peripheral-api-gpio#the-principles-short" class="hash-link" aria-label="Direct link to The principles, short" title="Direct link to The principles, short" translate="no">​</a></h2>
<ol>
<li class=""><strong>Hide the hardware, not the intent.</strong> The user says <em>which pin</em> and <em>what polarity</em>, not <em>which register</em>.</li>
<li class=""><strong>Make the invalid state visible.</strong> A status for everything that can fail, and an output only on success.</li>
<li class=""><strong>Put the knowledge into data.</strong> The board is a table that a loop reads.</li>
<li class=""><strong>Let the function own the order</strong> when the hardware cares about it.</li>
<li class=""><strong>Keep the interface the same, and say honestly where it is bent</strong> (<code>Init</code> with a parameter) and where the abstraction leaks (the vendor constants in the types).</li>
</ol>
<p>An interface has two readers: the user of today, and the maintainer of the next year. The decisions above are written for both, and the comments in the headers are the proof that somebody thought about the second.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="Architecture" term="Architecture"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Doxygen for embedded C: documentation that cannot be forgotten]]></title>
        <id>https://embedbits.cz/blog/doxygen-embedded-c</id>
        <link href="https://embedbits.cz/blog/doxygen-embedded-c"/>
        <updated>2026-10-06T20:00:00.000Z</updated>
        <summary type="html"><![CDATA[Every project has documentation, and every project has documentation that lies. A Word file with the description of the interface was correct in the week when it was written. A comment above the function is more honest, because it is a few lines from the code that it describes, but it is also written by the same people who forget. The way out is not more discipline, it is a tool that reads the comments, builds the documentation from them and fails the build when something is missing. That tool is Doxygen.]]></summary>
        <content type="html"><![CDATA[<p>Every project has documentation, and every project has documentation that lies. A Word file with the description of the interface was correct in the week when it was written. A comment above the function is more honest, because it is a few lines from the code that it describes, but it is also written by the same people who forget. The way out is not more discipline, it is a <strong>tool that reads the comments, builds the documentation from them and fails the build when something is missing</strong>. That tool is Doxygen.</p>
<p>This article shows what a documented module looks like in my projects, how it is generated, and how to make the documentation a part of the CI that cannot be skipped. The examples were built with Doxygen 1.9.8 and Graphviz, and the outputs are real.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-to-document-and-what-not">What to document, and what not<a href="https://embedbits.cz/blog/doxygen-embedded-c#what-to-document-and-what-not" class="hash-link" aria-label="Direct link to What to document, and what not" title="Direct link to What to document, and what not" translate="no">​</a></h2>
<p>My <a class="" href="https://embedbits.cz/docs/platform/embi-platform/coding-style">coding style</a> has one paragraph about it: Doxygen-style comments for all <strong>public</strong> functions, types and macros, in English, short and precise, <em>why</em> and not <em>what</em>. A few examples of the difference:</p>





















<table><thead><tr><th>A comment that costs nothing</th><th>A comment that helps</th></tr></thead><tbody><tr><td><code>/* initializes the module */</code></td><td><code>Clears the filter and marks the value as not valid. The module does not report a value until Temperature_Task() has run at least once.</code></td></tr><tr><td><code>/* returns the value */</code></td><td><code>Returns TEMPERATURE_REQUEST_OK if a valid value is available, TEMPERATURE_REQUEST_ERROR if the task has not run yet.</code></td></tr><tr><td><code>/* value */</code> (for a parameter)</td><td><code>Filtered temperature in tenths of a degree Celsius. Must not be NULL. Written only if the function returns TEMPERATURE_REQUEST_OK.</code></td></tr></tbody></table>
<p>The first column repeats the name of the function, which the reader can already see. The second column says what the reader <strong>cannot</strong> see: the unit, the valid range, who owns the memory, whether the output is written in the case of an error, from where the function can be called, what has to be done before it. For an embedded interface it is also the place for the information that is dangerous to guess: <em>is it safe to call it from an interrupt</em>, <em>how long can it block</em>, <em>is the pointer allowed to be NULL</em>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-module-in-the-files-of-the-platform">The module in the files of the platform<a href="https://embedbits.cz/blog/doxygen-embedded-c#the-module-in-the-files-of-the-platform" class="hash-link" aria-label="Direct link to The module in the files of the platform" title="Direct link to The module in the files of the platform" translate="no">​</a></h2>
<p>The templates of EmBi_Platform, from which every module starts, have the same documentation skeleton: the header of the file, with <code>\author</code>, <code>\file</code>, <code>\ingroup</code> and <code>\brief</code>, and above every function a block with a <code>\brief</code>, a description and a <code>\return</code>. The finite state machine template adds <code>\pre</code> for the preconditions and a block <code>\par Used global variables</code> with a list of the variables that the function reads (<code>in</code>), writes (<code>out</code>) or both (<code>in,out</code>), which is a surprisingly useful kind of documentation: the data flow of a function in three lines.</p>
<p>The whole module is one <strong>group</strong> in Doxygen. The <code>\ingroup Temperature</code> in each file says that the file belongs to the module, and the group itself is defined once, in the port file:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Temperature_Port.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \author Mr.Nobody</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \file Temperature_Port.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \ingroup Temperature</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Temperature module public functionality</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * The only header that other modules include.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \defgroup Temperature Temperature module</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Measures the temperature and provides a filtered value.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * The module has to be initialized by Temperature_Init() and its</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Temperature_Task() has to be called periodically. The latest filtered value</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * is read by Temperature_Get_Value().</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">TEMPERATURE_TEMPERATURE_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">TEMPERATURE_TEMPERATURE_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifdef</span><span class="token macro property"> </span><span class="token macro property expression">__cplusplus</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">extern</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"C"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== INCLUDES ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Temperature_Types.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ========================= EXPORTED FUNCTIONS ============================= */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Initializes the module.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Clears the filter and marks the value as not valid. The module does not</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * report a value until Temperature_Task() has run at least once.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \pre Called once, before the first Temperature_Task().</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Reads the sensor and updates the filtered value.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Shall be called periodically from the main loop or from a scheduler, it</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * takes about the same time on every call.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \note Not safe to be called from an interrupt: the function is not reentrant.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Provides the latest filtered temperature.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \param[out] value Filtered temperature in tenths of a degree Celsius. Must</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *                   not be NULL. It is written only if the function returns</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *                   \ref TEMPERATURE_REQUEST_OK.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \return \ref TEMPERATURE_REQUEST_OK if a valid value is available,</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *         \ref TEMPERATURE_REQUEST_ERROR if the task has not run yet.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_RequestState_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Get_Value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifdef</span><span class="token macro property"> </span><span class="token macro property expression">__cplusplus</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token macro property"> </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* TEMPERATURE_TEMPERATURE_PORT_H */</span><br></div></code></pre></div></div>
<p>The types have a short description of the type and of every value (the <code>/**&lt; ... */</code> comment behind a member documents the member on the same line):</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Temperature_Types.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \author Mr.Nobody</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \file Temperature_Types.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \ingroup Temperature</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Temperature module global types definition</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * This file contains the types that are used across the module and are</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * available for other modules through the port file.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">TEMPERATURE_TEMPERATURE_TYPES_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">TEMPERATURE_TEMPERATURE_TYPES_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== INCLUDES ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== TYPEDEFS ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/** Temperature in tenths of a degree Celsius, e.g. 253 means 25.3 degC. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">int16_t</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/** Enumeration used to signal the result of a request. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    TEMPERATURE_REQUEST_ERROR </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; The request failed, the output is not valid */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    TEMPERATURE_REQUEST_OK          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; The request succeeded                       */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_RequestState_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token macro property"> </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* TEMPERATURE_TEMPERATURE_TYPES_H */</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="generating-it">Generating it<a href="https://embedbits.cz/blog/doxygen-embedded-c#generating-it" class="hash-link" aria-label="Direct link to Generating it" title="Direct link to Generating it" translate="no">​</a></h2>
<p>Doxygen is configured by a file with a few hundred options. Writing it by hand is a mistake that is easy to avoid: the platform has the file as a template (<code>Doxyfile.in</code> in the Doxygen artifact) and fills it from CMake variables, and the projects only set the ones that differ from the defaults. The same is possible with the module of CMake itself, and this is the whole configuration of the example:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">CMakeLists.txt</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">cmake_minimum_required</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token property">VERSION</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.19</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">project</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DoxDemo C</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">find_package</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Doxygen REQUIRED dot</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_PROJECT_NAME        </span><span class="token string" style="color:rgb(195, 232, 141)">"Temperature module"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_OUTPUT_DIRECTORY    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BINARY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/docs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_FULL_PATH_NAMES     NO</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_GENERATE_LATEX      NO</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_QUIET               YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># The documentation is a contract: a missing description is an error.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_IF_UNDOCUMENTED     YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_IF_DOC_ERROR        YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_NO_PARAMDOC         YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_AS_ERROR            FAIL_ON_WARNINGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Graphs (the Graphviz artifact in the platform)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_HAVE_DOT                 YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_CALL_GRAPH               YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_CALLER_GRAPH             YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_DOT_IMAGE_FORMAT         svg</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">doxygen_add_docs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">docs Temperature COMMENT </span><span class="token string" style="color:rgb(195, 232, 141)">"Generating the documentation"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>and the build is one target:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-S</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">.</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-B</span><span class="token plain"> build </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-G</span><span class="token plain"> Ninja</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">--build</span><span class="token plain"> build </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">--target</span><span class="token plain"> docs</span><br></div></code></pre></div></div>
<p>The result is a folder with the HTML pages. The group of the module, with the files that belong to it and the description from the port file, looks like this:</p>
<p><img decoding="async" loading="lazy" alt="The page of the Temperature group in the generated HTML documentation" src="https://embedbits.cz/assets/images/doxygen-module-group-7e9b023f433e65035665cd32e2f490ba.png" width="1000" height="900" class="img_ev3q"></p>
<p>Doxygen also draws the <strong>include graph</strong> of every file and the <strong>call graph</strong> and <strong>caller graph</strong> of every documented function (<code>HAVE_DOT</code>, Graphviz: that is the reason why the platform has an artifact for it). The include graphs are worth a look from time to time: an arrow from an application file to an internal header of a module is the same problem that the <a class="" href="https://embedbits.cz/blog/file-organization-embedded-c">article about the file organization</a> describes, only seen from above.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-documentation-as-a-test">The documentation as a test<a href="https://embedbits.cz/blog/doxygen-embedded-c#the-documentation-as-a-test" class="hash-link" aria-label="Direct link to The documentation as a test" title="Direct link to The documentation as a test" translate="no">​</a></h2>
<p>This is the part that changes the discipline. Four options turn missing documentation from a "we should" into a "the build is red":</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_IF_UNDOCUMENTED   YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># a public member without a description</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_IF_DOC_ERROR      YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># a wrong tag, a parameter that does not exist</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_NO_PARAMDOC       YES</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># a function whose parameters are not described</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DOXYGEN_WARN_AS_ERROR          FAIL_ON_WARNINGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>With <code>FAIL_ON_WARNINGS</code> Doxygen goes through everything, prints <strong>all</strong> the warnings and only then fails (the plain <code>YES</code> stops at the first one). I tried it: I deleted the description of <code>Temperature_Task()</code> and the <code>\param</code> of <code>Temperature_Get_Value()</code> from the port file, and the build said:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Temperature/Temperature_Port.h:40: error: Member Temperature_Task(void) (function) of file Temperature_Port.h is not documented.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Temperature/Temperature_Port.h:45: error: parameters of member Temperature_Get_Value are not documented</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ninja: build stopped: subcommand failed.</span><br></div></code></pre></div></div>
<p>(The exit code of the command is 1, so the CI is red.) With the descriptions back, the same build finishes with no output at all and an exit code 0. A new function without a comment now cannot get to the main branch by mistake, and nobody has to be the one who remembers it in a review.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-a-good-documentation-of-an-interface-contains">What a good documentation of an interface contains<a href="https://embedbits.cz/blog/doxygen-embedded-c#what-a-good-documentation-of-an-interface-contains" class="hash-link" aria-label="Direct link to What a good documentation of an interface contains" title="Direct link to What a good documentation of an interface contains" translate="no">​</a></h2>
<p>For each function of a public interface, check the list:</p>
<ol>
<li class=""><strong>What it does</strong>, in one sentence, with the verb (<code>\brief</code>).</li>
<li class=""><strong>The parameters</strong>: the direction (<code>[in]</code>, <code>[out]</code>, <code>[in,out]</code>), the unit, the range, whether <code>NULL</code> is allowed.</li>
<li class=""><strong>The return value</strong>: every value that can be returned and what it means.</li>
<li class=""><strong>The preconditions</strong> (<code>\pre</code>): what has to be done before, for example the initialization.</li>
<li class=""><strong>The context</strong>: can it be called from an interrupt, does it block, how long does it take.</li>
<li class=""><strong>The side effects</strong>: what else it changes (a global state, a peripheral).</li>
</ol>
<p>If a function does not have an answer to one of these questions, the answer is in the code and the reader has to read it. That is the sign that the interface is not finished, and the exercise of writing the comment is often the moment when you find it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-it-fits-in-the-platform">Where it fits in the platform<a href="https://embedbits.cz/blog/doxygen-embedded-c#where-it-fits-in-the-platform" class="hash-link" aria-label="Direct link to Where it fits in the platform" title="Direct link to Where it fits in the platform" translate="no">​</a></h2>
<p>Each module of the platform has in its <code>CMakeLists.txt</code> a call that registers its folder for the documentation (when the Doxygen artifact is available in the project), and the root build has an option <code>DOXYGEN_ENABLED</code>. So the documentation of the whole firmware is generated by the same build as the firmware: <code>-DDOXYGEN_ENABLED=ON</code>. The artifacts (the Doxygen and Graphviz) are fetched in the version that the project has pinned, so the pages of today and of the next year look the same.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-checklist">A checklist<a href="https://embedbits.cz/blog/doxygen-embedded-c#a-checklist" class="hash-link" aria-label="Direct link to A checklist" title="Direct link to A checklist" translate="no">​</a></h2>
<ol>
<li class="">Every public function, type and macro has a description. The internal ones only where it is not obvious.</li>
<li class="">The description says what the reader cannot see in the signature: units, ranges, the context, the errors.</li>
<li class="">One group per module (<code>\defgroup</code> in the port file, <code>\ingroup</code> in the others).</li>
<li class=""><code>WARN_IF_UNDOCUMENTED</code>, <code>WARN_NO_PARAMDOC</code> and <code>FAIL_ON_WARNINGS</code> in the CI.</li>
<li class="">The graphs are on, and somebody looks at the include graph of the application once in a while.</li>
<li class="">The documentation is generated from the same build as the firmware, with the pinned tools.</li>
</ol>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="CMake" term="CMake"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[CMake for embedded firmware: a build that you can read]]></title>
        <id>https://embedbits.cz/blog/cmake-for-embedded-firmware</id>
        <link href="https://embedbits.cz/blog/cmake-for-embedded-firmware"/>
        <updated>2026-10-06T18:00:00.000Z</updated>
        <summary type="html"><![CDATA[An IDE project is a file that nobody reads the build is a text that you read, review, version and run in the CI exactly the same way as on your desk.]]></summary>
        <content type="html"><![CDATA[<p>An IDE project is a file that nobody reads: a few thousand lines of XML that the IDE writes and the IDE reads, and that nobody can review in a pull request. The build then exists only on the computer where somebody clicked it together. CMake solves it with a different philosophy: <strong>the build is a text that you read, review, version and run in the CI</strong> exactly the same way as on your desk.</p>
<p>The build system of the Embedbits platform (EmBi_Platform) is made in CMake, and this article explains the pieces that every embedded CMake build needs, on a small project that I built and ran: a toolchain file, flags with names, build types, the modules as libraries, the linker script, the files after the link and a test that runs the firmware in a simulator. All numbers and outputs are real.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-layers-the-project-and-the-platform">Two layers: the project and the platform<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#two-layers-the-project-and-the-platform" class="hash-link" aria-label="Direct link to Two layers: the project and the platform" title="Direct link to Two layers: the project and the platform" translate="no">​</a></h2>
<p>The platform splits the build into two parts, and the idea is worth stealing even for a small project. The root <code>CMakeLists.txt</code> of the product is a minimal entry point, and everything complicated lives in a separate script that is <strong>versioned and shared</strong> (a Git submodule), which the root includes:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">include</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_CURRENT_LIST_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/CMake/Build.cmake</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>The platform script knows the build types (<code>Debug</code>, <code>Release</code>, <code>UnitTest</code>, <code>IntegrationTest</code>), the checks of the parameters, the toolchain, the include paths and the registration of the modules. The product only fills in what is specific for it. A fix of the build is then a new version of the submodule and not an edit of ten products. The example below has both parts in one project to be short, but it keeps the same separation: <code>cmake/</code> is the "platform" and <code>CMakeLists.txt</code> is the "product".</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-example-project">The example project<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#the-example-project" class="hash-link" aria-label="Direct link to The example project" title="Direct link to The example project" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">cmake/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  arm-none-eabi.cmake       toolchain file</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  Flags.cmake               flags with names</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Bsp/Startup/                startup code and the linker script (see the article about main())</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Middlewares/Temperature/    a module as a library (see the article about file organization)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Application/                main.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">CMakeLists.txt</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-toolchain-file-the-compiler-is-not-the-pc">The toolchain file: the compiler is not the PC<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#the-toolchain-file-the-compiler-is-not-the-pc" class="hash-link" aria-label="Direct link to The toolchain file: the compiler is not the PC" title="Direct link to The toolchain file: the compiler is not the PC" translate="no">​</a></h2>
<p>CMake assumes that you build for the computer that you sit at. A toolchain file says otherwise:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">cmake/arm-none-eabi.cmake</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Toolchain file: tells CMake that the target is a bare-metal ARM and not the PC.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SYSTEM_NAME</span><span class="token plain">      Generic</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SYSTEM_PROCESSOR</span><span class="token plain"> arm</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_C_COMPILER</span><span class="token plain">   arm-none-eabi-gcc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_ASM_COMPILER</span><span class="token plain"> arm-none-eabi-gcc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_OBJCOPY</span><span class="token plain">      arm-none-eabi-objcopy</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SIZE</span><span class="token plain">         arm-none-eabi-size</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># The compiler cannot link a PC executable: the check of the compiler builds a static library only.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_TRY_COMPILE_TARGET_TYPE</span><span class="token plain"> STATIC_LIBRARY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Search for programs on the PC, for libraries and headers only in the toolchain.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_FIND_ROOT_PATH_MODE_PROGRAM</span><span class="token plain"> NEVER</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_FIND_ROOT_PATH_MODE_LIBRARY</span><span class="token plain"> ONLY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_FIND_ROOT_PATH_MODE_INCLUDE</span><span class="token plain"> ONLY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>The line that people forget is <code>CMAKE_TRY_COMPILE_TARGET_TYPE</code>. At the beginning CMake builds a test program to check that the compiler works, and a bare-metal compiler cannot link a program for a PC (there is no operating system, no <code>main</code> that is called by anybody). With a static library as the target of the check, the test passes. The toolchain is given on the command line, once, when the build folder is created:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-S</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">.</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-B</span><span class="token plain"> build-debug </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-G</span><span class="token plain"> Ninja </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-DCMAKE_TOOLCHAIN_FILE</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">cmake/arm-none-eabi.cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-DCMAKE_BUILD_TYPE</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">Debug</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">--build</span><span class="token plain"> build-debug</span><br></div></code></pre></div></div>
<p>The same source folder with another <code>-B</code> is another build: a <code>build-release</code> next to it, or one for the unit tests on the PC, without the toolchain file.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="flags-with-names">Flags with names<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#flags-with-names" class="hash-link" aria-label="Direct link to Flags with names" title="Direct link to Flags with names" translate="no">​</a></h2>
<p>A line like <code>-mcpu=cortex-m4 -mthumb -mfloat-abi=soft -ffunction-sections ...</code> is hard to review, because nobody knows which part of it is important. The platform has a file <code>Flags.cmake</code> with a variable for every flag, with a comment (<code>THUMB_MODE</code>, <code>ENABLE_ALL_WARNINGS</code>, <code>REMOVE_UNUSED_FUNCTIONS</code>, <code>ENABLE_GC_SECTIONS</code>, <code>PRINT_MEMORY_USAGE</code> and so on, plus the CPU and FPU variants from the Cortex-M0 to the M85). The project then reads like a sentence. Mine has only what the example needs:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">cmake/Flags.cmake</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Flags with names, so the CMakeLists.txt reads like a sentence.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">MCU_FLAGS             -mcpu=cortex-m4 -mthumb -mfloat-abi=soft</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">WARNING_FLAGS         -Wall -Wextra -Wshadow -Wconversion</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">SECTION_FLAGS         -ffunction-sections -fdata-sections</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># one section per function and variable...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GC_FLAGS              -Wl,--gc-sections</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">                          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ...so the linker can drop the unused ones</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">STARTUP_LINK_FLAGS    -nostartfiles</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DEBUG_OPTIONS         -Og -g3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">RELEASE_OPTIONS       -Os -g0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-cmakeliststxt">The CMakeLists.txt<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#the-cmakeliststxt" class="hash-link" aria-label="Direct link to The CMakeLists.txt" title="Direct link to The CMakeLists.txt" translate="no">​</a></h2>
<p>The whole root file of the example, 80 lines:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">CMakeLists.txt</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">cmake_minimum_required</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token property">VERSION</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.19</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># The toolchain file has to be given before project(), see the command line.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">project</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">CmakeDemo C</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">enable_testing</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">option</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GC_SECTIONS </span><span class="token string" style="color:rgb(195, 232, 141)">"Let the linker remove the unused functions and data"</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">ON</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">include</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">cmake/Flags.cmake</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># CMake adds its own flags to every configuration (-O3 -DNDEBUG for Release, -g for Debug).</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># The flags of the project are in Flags.cmake, so the defaults are cleared.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_C_FLAGS_DEBUG</span><span class="token plain">   </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_C_FLAGS_RELEASE</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ---- build type: flags of the configuration ----</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">NOT</span><span class="token plain"> </span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BUILD_TYPE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BUILD_TYPE</span><span class="token plain"> Debug</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">endif</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BUILD_TYPE</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">STREQUAL</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"Debug"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUILD_OPTIONS </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">DEBUG_OPTIONS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">elseif</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BUILD_TYPE</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">STREQUAL</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"Release"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUILD_OPTIONS </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">RELEASE_OPTIONS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">else</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">message</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">FATAL_ERROR </span><span class="token string" style="color:rgb(195, 232, 141)">"Unknown build type '</span><span class="token string interpolation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token string interpolation variable" style="color:rgb(191, 199, 213)">CMAKE_BUILD_TYPE</span><span class="token string interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string" style="color:rgb(195, 232, 141)">', use Debug or Release"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">endif</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_C_STANDARD</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">11</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_C_STANDARD_REQUIRED</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">ON</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_EXPORT_COMPILE_COMMANDS</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">ON</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ---- flags for everything that is built here ----</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_compile_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">MCU_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">WARNING_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">BUILD_OPTIONS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GC_SECTIONS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">add_compile_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">SECTION_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">endif</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_link_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">MCU_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ---- modules ----</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_subdirectory</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Middlewares/Temperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># The startup code is an OBJECT library: its objects always end up in the executable,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># without relying on the linker to pull them out of an archive.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_library</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Startup OBJECT Bsp/Startup/startup.c</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># GCC may turn the copy and zero loops of the startup code into calls of memcpy() and memset()</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">target_compile_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Startup </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"> -fno-tree-loop-distribute-patterns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ---- the firmware ----</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">LINKER_SCRIPT </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/Bsp/Startup/link.ld</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_executable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">firmware.elf Application/main.c Application/Unused.c </span><span class="token punctuation" style="color:rgb(199, 146, 234)">$&lt;</span><span class="token namespace" style="color:rgb(178, 204, 214)">TARGET_OBJECTS</span><span class="token plain">:Startup</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">target_link_libraries</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">firmware.elf </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"> Temperature_Lib</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">target_link_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">firmware.elf </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">STARTUP_LINK_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    -T </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">LINKER_SCRIPT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    -Wl,-Map=firmware.map</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    -Wl,--print-memory-usage</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    -Wl,--no-warn-rwx-segments</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GC_SECTIONS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">target_link_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">firmware.elf </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">GC_FLAGS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">endif</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set_target_properties</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">firmware.elf </span><span class="token namespace" style="color:rgb(178, 204, 214)">PROPERTIES</span><span class="token plain"> </span><span class="token property">LINK_DEPENDS</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">LINKER_SCRIPT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ---- after the link: the files that you flash and a size report ----</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_custom_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">TARGET firmware.elf POST_BUILD</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMAND </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_OBJCOPY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> -O binary firmware.elf firmware.bin</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMAND </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_OBJCOPY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> -O ihex   firmware.elf firmware.hex</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMAND </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SIZE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> firmware.elf</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMENT </span><span class="token string" style="color:rgb(195, 232, 141)">"Creating firmware.bin, firmware.hex and the size report"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ---- run it in the simulator as a test ----</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">find_program</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">QEMU qemu-system-arm</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">QEMU</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">add_test</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token property">NAME</span><span class="token plain"> firmware_runs_in_qemu</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        COMMAND </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">QEMU</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> -M netduinoplus2 -nographic -semihosting-config enable=on,target=native -kernel firmware.elf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">set_tests_properties</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">firmware_runs_in_qemu </span><span class="token namespace" style="color:rgb(178, 204, 214)">PROPERTIES</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token property">PASS_REGULAR_EXPRESSION</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"temperature module works"</span><span class="token plain"> </span><span class="token property">TIMEOUT</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">10</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">endif</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>Let me explain a few lines that decide whether the firmware will be right.</p>
<p><strong>Build types with explicit flags.</strong> There are only two, <code>Debug</code> (<code>-Og -g3</code>: fast enough and debuggable) and <code>Release</code> (<code>-Os -g0</code>: small and without the debug information), and anything else stops the configuration with an error message. The platform has two more, <code>UnitTest</code> and <code>IntegrationTest</code>: in the first one the <code>TARGET_MCU</code> is not even needed, because it builds for the PC.</p>
<p><strong>The default flags of CMake.</strong> This is a trap. CMake adds its own flags to each configuration, <code>-O3 -DNDEBUG</code> for <code>Release</code> and <code>-g</code> for <code>Debug</code>, before your own. In the first version of the example the compile command of the release looked like this:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">-O3 -DNDEBUG -std=gnu11 -mcpu=cortex-m4 ... -Os -g0 -ffunction-sections ...</span><br></div></code></pre></div></div>
<p>The last <code>-O</code> wins, so it was <code>-Os</code>, but the <code>-DNDEBUG</code> (which switches the <code>assert()</code> off) was there although I never asked for it. If you want to know what you build, clear the defaults (<code>set(CMAKE_C_FLAGS_RELEASE "")</code>) and write everything in your own file. The way to see what really goes to the compiler is <code>compile_commands.json</code>, which the <code>CMAKE_EXPORT_COMPILE_COMMANDS</code> option creates: it is also the file that the editors and <code>clang-tidy</code> read.</p>
<p><strong>The startup code is an <code>OBJECT</code> library.</strong> The objects of such a library are put into the executable directly, without relying on the linker to pull them out of an archive.</p>
<p><strong>The linker script is a dependency</strong> (<code>LINK_DEPENDS</code>): when it changes, the firmware is linked again.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-modules-are-libraries">The modules are libraries<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#the-modules-are-libraries" class="hash-link" aria-label="Direct link to The modules are libraries" title="Direct link to The modules are libraries" translate="no">​</a></h2>
<p>Each module is a static library with a list of its <strong>own</strong> sources and its public headers (<a class="" href="https://embedbits.cz/blog/file-organization-embedded-c">the article about the file organization</a> explains why). The application links the library, and with it gets the include path of the public headers and nothing else. In the CMake file of the module there is no <code>file(GLOB ...)</code>: the sources are listed one by one, so a new file is a visible change in a pull request and a file that is left in the folder by accident does not end up in the firmware.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="target_mcu-one-name-several-definitions"><code>TARGET_MCU</code>: one name, several definitions<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#target_mcu-one-name-several-definitions" class="hash-link" aria-label="Direct link to target_mcu-one-name-several-definitions" title="Direct link to target_mcu-one-name-several-definitions" translate="no">​</a></h2>
<p>The platform builds are started with <code>-DTARGET_MCU=STM32G474xE</code>. The script takes the name apart with a regular expression, and from one parameter it makes the definitions for the code (<code>STM32G474xx</code> and <code>STM32G4xx</code>), which the vendor headers use to select the right device. The same logic, run on four names:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">STM32G474xE  -&gt;  MCU_ID STM32G474xx, MCU_FAMILY_ID STM32G4xx</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">STM32U5A5xx  -&gt;  MCU_ID STM32U5A5xx, MCU_FAMILY_ID STM32U5xx</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">STM32F407VG  -&gt;  MCU_ID STM32F407xx, MCU_FAMILY_ID STM32F4xx</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">STM32H563ZI  -&gt;  MCU_ID STM32H563xx, MCU_FAMILY_ID STM32H5xx</span><br></div></code></pre></div></div>
<p>This is the link to the article about the <a class="" href="https://embedbits.cz/blog/bsp-stm32-families-git-branches">STM32 families and the branches</a>: the family decides which branch of the BSP is in the tree, and the MCU name decides the definitions and the linker script.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-linker-tells-you">What the linker tells you<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#what-the-linker-tells-you" class="hash-link" aria-label="Direct link to What the linker tells you" title="Direct link to What the linker tells you" translate="no">​</a></h2>
<p><code>-Wl,--print-memory-usage</code> prints at the end of every link how much of each memory is used, <code>-Wl,-Map=firmware.map</code> writes the address of everything, and the post-build step prints the size:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Memory region         Used Size  Region Size  %age Used</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">           FLASH:         276 B         1 MB      0.03%</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">             RAM:           8 B       128 KB      0.01%</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   text	   data	    bss	    dec	    hex	filename</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    276	      0	      8	    284	    11c	firmware.elf</span><br></div></code></pre></div></div>
<p>Two experiments that I did with these numbers show why the flags are in the build and not in somebody's head.</p>
<p><strong>The linker can throw away what nobody calls.</strong> With <code>-ffunction-sections -fdata-sections</code> every function is in its own section, and <code>-Wl,--gc-sections</code> lets the linker remove the unreferenced ones. The example has a function <code>Unused_Checksum()</code> that nobody calls:</p>

















<table><thead><tr><th>Build</th><th>Code size</th></tr></thead><tbody><tr><td>Release, without the section flags and without <code>--gc-sections</code></td><td>324 B</td></tr><tr><td>Release, with them (<code>-DGC_SECTIONS=ON</code>)</td><td><strong>276 B</strong></td></tr></tbody></table>
<p>The 48 bytes difference is exactly the checksum function. In a real project with a vendor library, which has hundreds of functions of which you call ten, the difference is in kilobytes.</p>
<p><strong>The compiler can add memory behind your back.</strong> The first release build of the example had <strong>772 B</strong>, almost three times more than the debug build (288 B). The map file showed <code>memcpy</code> and <code>memset</code> from the standard library. The cause: when the optimization is on, GCC recognizes the loops in the startup code (the copy of <code>.data</code> and the zeroing of <code>.bss</code>) as a copy and a fill, and replaces them with calls of these two functions, which then come with their code from the library. One flag on the startup object fixes it, and the result is <strong>276 B</strong>:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">target_compile_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Startup </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"> -fno-tree-loop-distribute-patterns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>Apart from the size, there is a second reason to care: the startup code runs <em>before</em> the memory is initialized, and the less library code it uses, the less can go wrong (see the article about <a class="" href="https://embedbits.cz/blog/before-main-startup-linker">what happens before <code>main()</code></a>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="after-the-link-what-you-flash-and-what-you-test">After the link: what you flash, and what you test<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#after-the-link-what-you-flash-and-what-you-test" class="hash-link" aria-label="Direct link to After the link: what you flash, and what you test" title="Direct link to After the link: what you flash, and what you test" translate="no">​</a></h2>
<p>The <code>POST_BUILD</code> command makes <code>firmware.bin</code> and <code>firmware.hex</code> (the formats that the programmers read) from the ELF file and prints the size. The last part of the example is a test: <code>add_test</code> runs the firmware in QEMU and <code>ctest</code> checks that it printed the expected text:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">ctest --test-dir build-debug</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">1/1 Test #1: firmware_runs_in_qemu ............   Passed    0.05 sec</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">100% tests passed, 0 tests failed out of 1</span><br></div></code></pre></div></div>
<p>It is a <em>smoke test</em> (does the firmware start and reach its <code>main()</code>?), and it runs in a fraction of a second on every commit. It does not replace a test on the hardware, but a build that does not start is found in the CI and not at the desk. The tests of the modules on the PC are a different build of the same CMake project (the <a class="" href="https://embedbits.cz/blog/unit-testing-unity-cmock">article about Unity and CMock</a> shows one).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-checklist">A checklist<a href="https://embedbits.cz/blog/cmake-for-embedded-firmware#a-checklist" class="hash-link" aria-label="Direct link to A checklist" title="Direct link to A checklist" translate="no">​</a></h2>
<ol>
<li class="">A toolchain file, and <code>CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY</code>.</li>
<li class="">The flags in one file with names, the CMake defaults of the configurations cleared.</li>
<li class="">Each module is a library with an explicit list of sources and public headers.</li>
<li class=""><code>-ffunction-sections -fdata-sections</code> and <code>--gc-sections</code>, always.</li>
<li class=""><code>--print-memory-usage</code> and the map file in every link, <code>size</code> after it.</li>
<li class=""><code>compile_commands.json</code> for the editor and the static analysis.</li>
<li class="">The linker script is a dependency of the firmware.</li>
<li class="">A smoke test in a simulator in the CI.</li>
<li class="">Look at the size of the <em>release</em> build from time to time. If it grows without a reason, the map file knows why.</li>
</ol>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="CMake" term="CMake"/>
        <category label="STM32" term="STM32"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Interrupts and main(): how to share data safely]]></title>
        <id>https://embedbits.cz/blog/interrupts-and-main-shared-data</id>
        <link href="https://embedbits.cz/blog/interrupts-and-main-shared-data"/>
        <updated>2026-10-06T14:00:00.000Z</updated>
        <summary type="html"><![CDATA[An interrupt handler and the main loop are two programs that run in the same memory and do not know about each other. The C compiler does not know that the interrupt exists, and the CPU does not know that two variables belong together. The programmer is the only one who knows, and the bugs that follow are the worst kind: they appear once in a thousand runs, they disappear when you attach the debugger and they never appear in the code review, because the code looks right.]]></summary>
        <content type="html"><![CDATA[<p>An interrupt handler and the main loop are two programs that run in the same memory and do not know about each other. The C compiler does not know that the interrupt exists, and the CPU does not know that two variables belong together. The programmer is the only one who knows, and the bugs that follow are the worst kind: they appear once in a thousand runs, they disappear when you attach the debugger and they never appear in the code review, because the code looks right.</p>
<p>This article goes through the three problems of the shared data, one by one, with the code that <strong>fails</strong>, and then shows the patterns that work. The experiments run on a Cortex-M4 (in QEMU, on a model of an STM32F4 board) or on a PC, and the outputs are real.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="problem-1-the-compiler-does-not-see-the-interrupt">Problem 1: the compiler does not see the interrupt<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#problem-1-the-compiler-does-not-see-the-interrupt" class="hash-link" aria-label="Direct link to Problem 1: the compiler does not see the interrupt" title="Direct link to Problem 1: the compiler does not see the interrupt" translate="no">​</a></h2>
<p>The simplest communication between an interrupt and the main loop is a flag. The interrupt sets it, the main loop waits for it:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">main.c (a part)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifdef</span><span class="token macro property"> </span><span class="token macro property expression">USE_VOLATILE</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">volatile</span><span class="token plain"> bool dataReady</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> bool dataReady</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">SysTick_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    dataReady </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">SysTick_Start</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1000u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token plain">dataReady</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* waiting for the interrupt */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"the interrupt was seen\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Quit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>This is the whole program, and with the optimization <code>-O2</code> it <strong>never finishes</strong>. I ran it in QEMU with the SysTick as the interrupt source (the interrupt fires and sets the flag), and compared the version with and without <code>volatile</code>:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">--- without volatile</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">(no output, the program was killed by the timeout after 5 s)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">--- with volatile</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">the interrupt was seen</span><br></div></code></pre></div></div>
<p>Why? Look at what the compiler generated for the loop in the first version:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain"> 8000062:  ldrb  r3, [r1, #0]       @ read the flag once</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"> 8000064:  cbnz  r3, 8000068        @ non-zero: leave the loop</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"> 8000066:  b.n   8000066            @ zero: jump to itself, forever</span><br></div></code></pre></div></div>
<p>The compiler reasons about the code of <code>main()</code> alone, and in that code nobody writes to <code>dataReady</code>. So the value cannot change, it is enough to read it once, and the loop becomes an infinite loop. Exactly what you asked for, from its point of view. With <code>volatile</code> the compiler has to read the variable from the memory at every pass:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain"> 8000062:  ldrb  r3, [r2, #0]       @ read the flag in every pass</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"> 8000064:  cmp   r3, #0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"> 8000066:  beq.n 8000062</span><br></div></code></pre></div></div>
<p>The lesson: <strong>every variable that is shared between an interrupt and the main code has to be <code>volatile</code>.</strong> The same is true for every register of a peripheral, which is the reason why the register definitions in the CMSIS headers are <code>volatile</code>. Keep in mind that this works in the debug build (<code>-O0</code>) without it, and fails in the release build, which is why the bug is found late.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="problem-2-volatile-does-not-make-it-atomic">Problem 2: <code>volatile</code> does not make it atomic<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#problem-2-volatile-does-not-make-it-atomic" class="hash-link" aria-label="Direct link to problem-2-volatile-does-not-make-it-atomic" title="Direct link to problem-2-volatile-does-not-make-it-atomic" translate="no">​</a></h2>
<p><code>volatile</code> says "read and write the memory every time". It does not say "all at once". The innocent line <code>counter++</code> is three instructions:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Increment_Plain:</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   ldr   r2, [pc, #8]       @ address of the counter</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   ldr   r3, [r2, #0]       @ 1. load the value</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   adds  r3, #1             @ 2. add one</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   str   r3, [r2, #0]       @ 3. store it back</span><br></div></code></pre></div></div>
<p>If the interrupt arrives between the load and the store, and the interrupt also increments the counter, then one of the two increments is <strong>lost</strong>: the main code stores the old value plus one over the value that the interrupt has just stored. The timeline:</p>



































<table><thead><tr><th>Step</th><th>Main code</th><th>Interrupt</th><th>Counter</th></tr></thead><tbody><tr><td>1</td><td>loads 5</td><td></td><td>5</td></tr><tr><td>2</td><td></td><td>loads 5, adds 1, stores 6</td><td>6</td></tr><tr><td>3</td><td>adds 1 (it has 5 in the register)</td><td></td><td>6</td></tr><tr><td>4</td><td>stores 6</td><td></td><td><strong>6, should be 7</strong></td></tr></tbody></table>
<p>I wanted to show it on the Cortex-M4 too, and it did not work: in 200 000 increments with an interrupt every few instructions, QEMU lost nothing. That is probably because QEMU checks for the interrupts between the blocks of the translated code, so one never lands between the <code>ldr</code> and the <code>str</code>. It is a useful reminder that <strong>a simulator does not prove the absence of a race condition</strong>: the real MCU can interrupt after every instruction. The same race, in a place where it is easy to reproduce, is two threads on a PC:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">host_race.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;pthread.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdio.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">INCREMENTS</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">2000000u</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">volatile</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> plainCounter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">_Atomic</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain">  atomicCounter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token function" style="color:rgb(130, 170, 255)">Worker</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">argument</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">argument</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> INCREMENTS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        plainCounter</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* load, add, store: not atomic */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">atomic_fetch_add</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">atomicCounter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* one indivisible operation    */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">pthread_t</span><span class="token plain"> first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">pthread_create</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Worker</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">pthread_create</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Worker</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">pthread_join</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">pthread_join</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">printf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"expected        %u\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> INCREMENTS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">printf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"plain counter   %u (lost %u)\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> plainCounter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> INCREMENTS </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> plainCounter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">printf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"atomic counter  %u (lost %u)\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> atomicCounter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> INCREMENTS </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> atomicCounter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">expected        4000000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">plain counter   2652421 (lost 1347579)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">atomic counter  4000000 (lost 0)</span><br></div></code></pre></div></div>
<p>A third of all increments is lost, and the results differ from run to run. The thread on a PC and the interrupt on an MCU are in this respect the same thing: a second flow of control that can strike between two instructions. The same applies to everything that is bigger than the word of the CPU: a 64-bit timestamp or a structure with two fields can be read half old and half new (<em>torn read</em>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="three-ways-to-solve-it">Three ways to solve it<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#three-ways-to-solve-it" class="hash-link" aria-label="Direct link to Three ways to solve it" title="Direct link to Three ways to solve it" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-one-writer-for-every-variable-the-best-one">1. One writer for every variable (the best one)<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#1-one-writer-for-every-variable-the-best-one" class="hash-link" aria-label="Direct link to 1. One writer for every variable (the best one)" title="Direct link to 1. One writer for every variable (the best one)" translate="no">​</a></h3>
<p>The most robust solution is to design the data so that <strong>every variable is written by one side only</strong>. The interrupt writes the flag, the main code only reads it and does not clear it (or the other way around). Without two writers there is nothing to lose. If both sides need to change the same thing, they should not share it: each one has its own variable (the counter of the interrupts is <code>isrCalls</code>, the counter of the main code is a different one), and the sum is made by the reader.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-a-critical-section">2. A critical section<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#2-a-critical-section" class="hash-link" aria-label="Direct link to 2. A critical section" title="Direct link to 2. A critical section" translate="no">​</a></h3>
<p>When two writers are unavoidable, the interrupts are disabled for the time of the operation. The correct way is to <strong>save the state and restore it</strong>, and not to enable the interrupts at the end blindly, because the function may have been called with the interrupts already disabled:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Increment_CriticalSection:</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   mrs   r1, PRIMASK        @ save the state of the mask</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   cpsid i                  @ disable the interrupts</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   ldr   r3, [r2, #0]</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   adds  r3, #1</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   str   r3, [r2, #0]</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   msr   PRIMASK, r1        @ restore the state, as it was</span><br></div></code></pre></div></div>
<p>The price is the latency: during the section no interrupt can run. So the section has to be as short as a few instructions, and without a function call, a loop or a wait inside.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-an-atomic-operation">3. An atomic operation<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#3-an-atomic-operation" class="hash-link" aria-label="Direct link to 3. An atomic operation" title="Direct link to 3. An atomic operation" translate="no">​</a></h3>
<p>For a single word (a counter, a flag with a count) the processor has the instructions <code>LDREX</code> and <code>STREX</code>: the store succeeds only if nothing touched the address since the load, and when it does not, the loop repeats. The compiler generates them for you from the standard operation:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Increment_Atomic:</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   ldrex r1, [r3]           @ load and mark the address</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   adds  r1, #1</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   strex r2, r1, [r3]       @ store only if nobody has touched it, r2 = 0 on success</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   cmp   r2, #0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   bne.n Increment_Atomic   @ somebody did: try again</span><br></div></code></pre></div></div>
<p>in C it is one line, <code>__atomic_fetch_add(&amp;counter, 1u, __ATOMIC_RELAXED)</code> (or <code>atomic_fetch_add()</code> from <code>&lt;stdatomic.h&gt;</code>). It does not disable the interrupts, so it does not add the latency. It works for a single variable; for two variables that belong together it does not help.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-pattern-that-is-used-the-most-a-ring-buffer">The pattern that is used the most: a ring buffer<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#the-pattern-that-is-used-the-most-a-ring-buffer" class="hash-link" aria-label="Direct link to The pattern that is used the most: a ring buffer" title="Direct link to The pattern that is used the most: a ring buffer" translate="no">​</a></h2>
<p>The most common thing that an interrupt gives to the main code is a stream of data: the bytes received by the UART, the samples of the ADC. The interrupt cannot process them (it has to be short), so it puts them in a <strong>queue</strong>, and the main code takes them out in a quiet moment. This is the producer-consumer problem with <em>one producer</em> (the interrupt) and <em>one consumer</em> (the main code), and for this exact case a ring buffer needs <strong>no lock</strong>:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Ring.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">RING_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">RING_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdatomic.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">RING_SIZE</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">16u</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression">                       </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* has to be a power of two */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">RING_MASK</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> RING_SIZE </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">-</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">1u</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/*</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Single producer, single consumer ring buffer without any lock.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * head: written only by the producer, tail: written only by the consumer.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Both are free-running counters, the difference is the number of items.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain">         items</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">RING_SIZE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">atomic_uint_fast32_t</span><span class="token plain"> head</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">atomic_uint_fast32_t</span><span class="token plain"> tail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">ring_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> bool </span><span class="token function" style="color:rgb(130, 170, 255)">Ring_Push</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">ring_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">ring</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> item</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint_fast32_t</span><span class="token plain"> head </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">atomic_load_explicit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">head</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> memory_order_relaxed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint_fast32_t</span><span class="token plain"> tail </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">atomic_load_explicit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">tail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> memory_order_acquire</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">RING_SIZE </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">head </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> tail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                            </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* full, the producer decides what to do */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">items</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">head </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> RING_MASK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> item</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">atomic_store_explicit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">head</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> head </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> memory_order_release</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* publish the item */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> bool </span><span class="token function" style="color:rgb(130, 170, 255)">Ring_Pop</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">ring_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">ring</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">item</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint_fast32_t</span><span class="token plain"> tail </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">atomic_load_explicit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">tail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> memory_order_relaxed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint_fast32_t</span><span class="token plain"> head </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">atomic_load_explicit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">head</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> memory_order_acquire</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">head </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> tail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                            </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* empty */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">item </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">items</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">tail </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> RING_MASK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">atomic_store_explicit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">ring</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">tail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> tail </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> memory_order_release</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* free the slot */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<p>Why is it correct?</p>
<ul>
<li class=""><code>head</code> is written <strong>only by the producer</strong> and <code>tail</code> <strong>only by the consumer</strong>. There is no variable with two writers, so no update can be lost: this is the first solution above, built into the structure.</li>
<li class="">The counters are free-running (they are never reset). The number of items is <code>head - tail</code>, and thanks to the unsigned arithmetic it is correct even after the counters overflow. With the size a power of two, the position is a simple mask instead of a division.</li>
<li class="">The <strong>order</strong> matters: the producer writes the item and <strong>after that</strong> publishes it by moving <code>head</code> (<code>memory_order_release</code>), and the consumer reads <code>head</code> first (<code>memory_order_acquire</code>) and only then the item. On a single Cortex-M core the order in which the compiler writes is the only thing that matters, and the atomics keep it. On an MCU with two cores (some of the STM32H7 have two) or with a cache, the same code is still correct, which is the reason to write it in this form and not with a <code>volatile</code> that happens to work.</li>
<li class="">The producer does not wait. A full buffer means "drop the item and count it", because an interrupt cannot wait for anybody. The counter of the drops tells you in the test that the buffer is too small.</li>
</ul>
<p>I tested it two ways. On a PC with two threads, a producer and a consumer, pass 20 million items through a buffer of 16 slots:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">items 20000000, order errors 0</span><br></div></code></pre></div></div>
<p>and on the Cortex-M4 in QEMU: the SysTick interrupt is the producer and <code>main()</code> is the consumer, with 5000 items:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">items received  5000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">order errors    0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">full buffer hits 0</span><br></div></code></pre></div></div>
<p>The first test is the harder one (the two threads really run in parallel on two cores), the second one is the real situation of an MCU. It is also a perfect candidate for the unit test on a PC, as in the article about <a class="" href="https://embedbits.cz/blog/unit-testing-unity-cmock">unit testing with Unity and CMock</a>: the module is independent of the hardware.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-for-the-interrupt-handlers">Rules for the interrupt handlers<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#rules-for-the-interrupt-handlers" class="hash-link" aria-label="Direct link to Rules for the interrupt handlers" title="Direct link to Rules for the interrupt handlers" translate="no">​</a></h2>
<ol>
<li class=""><strong>Short.</strong> Read the register, save the data, set the flag, clear the pending flag, return. The processing is done in the main code.</li>
<li class=""><strong>No waiting, no allocation, no <code>printf</code>.</strong> Nothing that blocks, takes a long time or calls a function that is not safe to call from an interrupt (it is <em>non-reentrant</em>, if it uses a static buffer inside).</li>
<li class=""><strong>Everything shared is <code>volatile</code> or atomic</strong>, and every variable has a defined writer.</li>
<li class=""><strong>Do not share more than you must.</strong> A flag or a queue between the sides, and not a structure of ten fields.</li>
<li class=""><strong>Think about the priority.</strong> An interrupt of a higher priority can interrupt another interrupt. A variable shared between two interrupts has the same problem as one shared with the main code.</li>
</ol>
<p>In the Embedbits BSP, the peripheral modules (e.g. USART) have a polling, an interrupt and a DMA variant of the data handling, and the interrupt variant is exactly this: a handler on the MCAL level that takes the data from the peripheral and passes it to the application through a buffer, while the <code>Task</code> of the module runs in the main loop and does the processing.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://embedbits.cz/blog/interrupts-and-main-shared-data#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>



































<table><thead><tr><th>The problem</th><th>The symptom</th><th>The cure</th></tr></thead><tbody><tr><td>The compiler does not see the interrupt</td><td>Works with <code>-O0</code>, an endless loop with <code>-O2</code></td><td><code>volatile</code> on every shared variable</td></tr><tr><td><code>counter++</code> is not atomic</td><td>A count that is sometimes too small</td><td>One writer per variable, a critical section or <code>atomic_fetch_add</code></td></tr><tr><td>More than a word</td><td>Half old, half new value</td><td>A critical section, or a sequence number, or a queue</td></tr><tr><td>A stream of data</td><td>Lost or mixed bytes</td><td>A ring buffer with one producer and one consumer</td></tr><tr><td>The test passes in the simulator</td><td>A bug in the field</td><td>Remember that the simulator interrupts in different places than the MCU</td></tr></tbody></table>
<p>The three kinds of code in this article had one thing in common: they all <em>looked</em> right.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="STM32" term="STM32"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Finite state machines in practice: a button with debounce and long press]]></title>
        <id>https://embedbits.cz/blog/fsm-in-practice-button</id>
        <link href="https://embedbits.cz/blog/fsm-in-practice-button"/>
        <updated>2026-10-06T10:00:00.000Z</updated>
        <summary type="html"><![CDATA[In the first article about finite state machines I gave you the template and ended with "to be continued". This is the continuation, and the best way to continue a theory is a problem. I chose the one that every embedded project has and that nobody gets right on the first try: a push button.]]></summary>
        <content type="html"><![CDATA[<p>In the <a class="" href="https://embedbits.cz/blog/finite-state-machines">first article about finite state machines</a> I gave you the template and ended with "to be continued". This is the continuation, and the best way to continue a theory is a problem. I chose the one that every embedded project has and that nobody gets right on the first try: <strong>a push button</strong>.</p>
<p>A button looks trivial: a pin, high or low. But a mechanical contact <em>bounces</em>, so the pin does 1 0 1 1 0 1 before it settles, and the product usually wants two different things from the same button: a short press and a long press. Written with flags and counters in the main loop, it ends as a few <code>if</code>s that depend on each other in a way that nobody can explain after a month. A state machine solves it in a way that you can explain with a table.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-template-in-one-paragraph">The template in one paragraph<a href="https://embedbits.cz/blog/fsm-in-practice-button#the-template-in-one-paragraph" class="hash-link" aria-label="Direct link to The template in one paragraph" title="Direct link to The template in one paragraph" translate="no">​</a></h2>
<p>Every state has four routines, and each of them has exactly one job:</p>






























<table><thead><tr><th>Routine</th><th>Called</th><th>Job</th></tr></thead><tbody><tr><td><code>Entry</code></td><td>once, when the state is entered</td><td>prepare the state (clear the counter, create an event)</td></tr><tr><td><code>Execute</code></td><td>on every run of the machine, while it is in the state</td><td>do the work of the state (count, sample)</td></tr><tr><td><code>CheckLeave</code></td><td>on every run, after <code>Execute</code></td><td>decide whether to leave and where to: <strong>the only place where a transition is requested</strong></td></tr><tr><td><code>Leave</code></td><td>once, when the state is left</td><td>clean up</td></tr></tbody></table>
<p>The core of the machine runs <code>Execute</code> and <code>CheckLeave</code> of the actual state, and when the state changed, runs <code>Leave</code> of the old one and <code>Entry</code> of the new one. The routines never call each other and the code of the state machine contains nothing but the state machine. If you want to know why the device is in a state, you read <code>CheckLeave</code> of the previous one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="design-first-the-states-and-the-transitions">Design first: the states and the transitions<a href="https://embedbits.cz/blog/fsm-in-practice-button#design-first-the-states-and-the-transitions" class="hash-link" aria-label="Direct link to Design first: the states and the transitions" title="Direct link to Design first: the states and the transitions" translate="no">​</a></h2>
<p>The task runs every 10 ms and reads the raw contact. The debounce time is 50 ms and the limit of a long press is 1 second. Five states are enough:</p>





















































<table><thead><tr><th>State</th><th>Execute</th><th>Leaves when</th><th>To</th></tr></thead><tbody><tr><td><code>RELEASED</code></td><td>nothing</td><td>the contact is closed</td><td><code>DEBOUNCE_PRESS</code></td></tr><tr><td><code>DEBOUNCE_PRESS</code></td><td>counts the ticks</td><td>the contact opens again (it was a glitch)</td><td><code>RELEASED</code></td></tr><tr><td></td><td></td><td>the contact was closed for 50 ms</td><td><code>PRESSED</code></td></tr><tr><td><code>PRESSED</code></td><td>counts the ticks</td><td>the contact opens: <strong>short press</strong> event</td><td><code>DEBOUNCE_RELEASE</code></td></tr><tr><td></td><td></td><td>the contact is closed for 1 s</td><td><code>LONG_PRESS</code></td></tr><tr><td><code>LONG_PRESS</code></td><td>nothing, the <strong>long press</strong> event was created on the entry</td><td>the contact opens</td><td><code>DEBOUNCE_RELEASE</code></td></tr><tr><td><code>DEBOUNCE_RELEASE</code></td><td>counts the ticks of an open contact, a bounce resets the count</td><td>the contact was open for 50 ms</td><td><code>RELEASED</code></td></tr></tbody></table>
<p>Writing the table is the real work. When it is complete, the code is only a typing exercise. When it is not (what happens in the <code>LONG_PRESS</code> when the contact bounces on the release?), the table shows the hole before you write a line of C.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-code">The code<a href="https://embedbits.cz/blog/fsm-in-practice-button#the-code" class="hash-link" aria-label="Direct link to The code" title="Direct link to The code" translate="no">​</a></h2>
<p>The input comes from the BSP, so the module has no hardware dependency and can be tested on a PC (the same <em>seam</em> as in the article about <a class="" href="https://embedbits.cz/blog/unit-testing-unity-cmock">unit testing</a>). The port of the module is an <code>Init</code>, a <code>Task</code> and a function that returns the event once:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Button_Port.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">BUTTON_BUTTON_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">BUTTON_BUTTON_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_EVENT_NONE </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_EVENT_SHORT_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_EVENT_LONG_PRESS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_Event_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">           </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">           </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* call it every 10 ms */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">button_Event_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Get_Event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* returns the event once and clears it */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<p>The types follow the template. There is one change that I made on purpose: the table of the routines is <strong>indexed by the state</strong> and not searched, and the enumeration ends with <code>BUTTON_STATE_COUNT</code>, which has two uses.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Button.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_STATE_RELEASED </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Contact open, waiting for a press      */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_STATE_DEBOUNCE_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Contact closed, is it stable?          */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_STATE_PRESSED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Stable press, short or long?           */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_STATE_LONG_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Held longer than the limit             */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_STATE_DEBOUNCE_RELEASE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Contact open again, is it stable?      */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    BUTTON_STATE_COUNT             </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Number of the states, keep it the last */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_States_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_PtrToRoutine_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_PtrToRoutine_t</span><span class="token plain"> entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_PtrToRoutine_t</span><span class="token plain"> execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_PtrToRoutine_t</span><span class="token plain"> checkLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_PtrToRoutine_t</span><span class="token plain"> leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_Routines_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The first use is the table itself. With the designated initializers the position of a line does not matter, so a state cannot be linked to the wrong routines when someone adds a line in the middle (the template needs the comment "this array must have the same order as the state enum"):</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Button.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The table is indexed by the state, so the order of the lines does not matter. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_SM_Routines_t</span><span class="token plain"> stateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BUTTON_STATE_COUNT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BUTTON_STATE_RELEASED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain">         </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> Button_Released_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">        Button_Released_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                                        Button_Released_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">   Button_Released_Leave        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BUTTON_STATE_DEBOUNCE_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain">   </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> Button_DebouncePress_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">   Button_DebouncePress_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                                        Button_DebouncePress_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Button_DebouncePress_Leave </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BUTTON_STATE_PRESSED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain">          </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> Button_Pressed_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">         Button_Pressed_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                                        Button_Pressed_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">    Button_Pressed_Leave         </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BUTTON_STATE_LONG_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain">       </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> Button_LongPress_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">       Button_LongPress_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                                        Button_LongPress_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">  Button_LongPress_Leave       </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">BUTTON_STATE_DEBOUNCE_RELEASE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> Button_DebounceRelease_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Button_DebounceRelease_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                                        Button_DebounceRelease_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Button_DebounceRelease_Leave </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The second use is the core of the machine, in which the same constant replaces a hard-coded "last state" in the check of the range:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Button.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_HandleStateTransition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUTTON_STATE_COUNT </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> newState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        newState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_RELEASED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">      </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* invalid request: go to the safe state */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    stateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">actualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    stateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">actualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">checkLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">actualState </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> newState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        stateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">actualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        actualState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> newState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        stateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">actualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Look at what the core does <em>not</em> know: the buttons, the time, the events. Now the states. Most of the routines are one-liners:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Button.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ---- RELEASED ---- */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Released_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> stateTicks </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Released_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Released_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">isContactClosed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> newState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_DEBOUNCE_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Released_Leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ---- DEBOUNCE_PRESS: closed, but is it only a bounce? ---- */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebouncePress_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> stateTicks </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebouncePress_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> stateTicks</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebouncePress_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token plain">isContactClosed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        newState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_RELEASED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">               </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* a glitch, nothing happened */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUTTON_DEBOUNCE_TICKS </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> stateTicks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        newState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_PRESSED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebouncePress_Leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ---- PRESSED: a short press if released early, a long one if held ---- */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Pressed_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> stateTicks </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Pressed_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> stateTicks</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Pressed_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token plain">isContactClosed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        pendingEvent </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_EVENT_SHORT_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        newState     </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_DEBOUNCE_RELEASE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUTTON_LONG_PRESS_TICKS </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> stateTicks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        newState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_LONG_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Pressed_Leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ---- LONG_PRESS: the event is created once, on the entry ---- */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_LongPress_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> pendingEvent </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_EVENT_LONG_PRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_LongPress_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_LongPress_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token plain">isContactClosed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> newState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_DEBOUNCE_RELEASE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_LongPress_Leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ---- DEBOUNCE_RELEASE: open, has to stay open for the debounce time ---- */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebounceRelease_Entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> stateTicks </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebounceRelease_Execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> stateTicks </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> isContactClosed </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">stateTicks </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebounceRelease_CheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUTTON_DEBOUNCE_TICKS </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> stateTicks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> newState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> BUTTON_STATE_RELEASED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_DebounceRelease_Leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Some details that are worth a look:</p>
<ul>
<li class=""><code>Button_Task()</code> reads the input <strong>once</strong> per run and keeps it in <code>isContactClosed</code>. All routines of one run see the same value, even if the pin changes in the middle of the run.</li>
<li class="">The short press event is created in <code>Button_Pressed_CheckLeave()</code>, in the same place where the decision is made. The long press event is created in <code>Button_LongPress_Entry()</code>: the entry is called exactly once per transition, so the event cannot be created twice, whatever the contact does while the button is held.</li>
<li class="">The debounce of the release (<code>DEBOUNCE_RELEASE</code>) resets its counter whenever the contact is closed again. This is the answer to the bounce on the release: the machine waits until the contact is quiet for 50 ms.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-test">The test<a href="https://embedbits.cz/blog/fsm-in-practice-button#the-test" class="hash-link" aria-label="Direct link to The test" title="Direct link to The test" translate="no">​</a></h2>
<p>The test replaces <code>Bsp_Get_ButtonRaw()</code> by a function that reads a string: one character per 10 ms tick, <code>1</code> is the closed contact. The patterns are the story of the button, and the result is the string of the events, <code>S</code> for a short press and <code>L</code> for a long one:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">test_Button.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The fake input: one character per 10 ms tick, '1' = contact closed. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">inputPattern</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain">      inputIndex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_ButtonRaw</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> symbol </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> inputPattern</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">inputIndex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token char" style="color:rgb(130, 170, 255)">'\0'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> symbol</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> inputIndex</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token char" style="color:rgb(130, 170, 255)">'1'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> symbol</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Runs the machine over the whole pattern and returns the events as a string, S = short, L = long. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token function" style="color:rgb(130, 170, 255)">Run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">pattern</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">16</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> count </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    inputPattern </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> pattern</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    inputIndex   </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">memset</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">sizeof</span><span class="token plain"> events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> tick </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> tick </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">strlen</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">pattern</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">20u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> tick</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 20 extra ticks of an open contact */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">button_Event_t</span><span class="token plain"> event </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Button_Get_Event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUTTON_EVENT_SHORT_PRESS </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">count</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token char" style="color:rgb(130, 170, 255)">'S'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BUTTON_EVENT_LONG_PRESS  </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">count</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token char" style="color:rgb(130, 170, 255)">'L'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">pattern</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">expected</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">result </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">pattern</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">printf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"%-34s -&gt; %s\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token char" style="color:rgb(130, 170, 255)">'\0'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"(no event)"</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">assert</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">strcmp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">expected</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> longHold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">220</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"nothing happens"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                 </span><span class="token string" style="color:rgb(195, 232, 141)">"0000000000"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                              </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"a 20 ms glitch"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                  </span><span class="token string" style="color:rgb(195, 232, 141)">"0011000000"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                              </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"a clean 200 ms press"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">            </span><span class="token string" style="color:rgb(195, 232, 141)">"00111111111111111111110000000000"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"S"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"a press with a bouncing contact"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"0101101111111111111111011010000000000"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">   </span><span class="token string" style="color:rgb(195, 232, 141)">"S"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"a bounce on the release"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">         </span><span class="token string" style="color:rgb(195, 232, 141)">"001111111111111111111101001000000000"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"S"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">memset</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">longHold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token char" style="color:rgb(130, 170, 255)">'1'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">150u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> longHold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">150</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token char" style="color:rgb(130, 170, 255)">'\0'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 1.5 s */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"a 1.5 s hold"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                    longHold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                                  </span><span class="token string" style="color:rgb(195, 232, 141)">"L"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">memset</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">longHold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token char" style="color:rgb(130, 170, 255)">'1'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">99u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  longHold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">99</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token char" style="color:rgb(130, 170, 255)">'\0'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* just under the limit (+ debounce) */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"a 0.99 s hold"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                   longHold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">                                  </span><span class="token string" style="color:rgb(195, 232, 141)">"S"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">puts</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"all state machine tests passed"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The output of the run is the real one:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">nothing happens                    -&gt; (no event)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">a 20 ms glitch                     -&gt; (no event)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">a clean 200 ms press               -&gt; S</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">a press with a bouncing contact    -&gt; S</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">a bounce on the release            -&gt; S</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">a 1.5 s hold                       -&gt; L</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">a 0.99 s hold                      -&gt; S</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">all state machine tests passed</span><br></div></code></pre></div></div>
<p>The two last lines are the case that the flags always get wrong. A 1.5 second hold produces <strong>one</strong> long press and no short press after the release, and a hold just under the limit is a short press. Both are a consequence of the table and not of the careful programming.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-get-and-what-it-costs">What you get, and what it costs<a href="https://embedbits.cz/blog/fsm-in-practice-button#what-you-get-and-what-it-costs" class="hash-link" aria-label="Direct link to What you get, and what it costs" title="Direct link to What you get, and what it costs" translate="no">​</a></h2>
<p><strong>You get:</strong></p>
<ul>
<li class="">a <strong>readable specification</strong>: the table above and the code are the same thing,</li>
<li class="">the <strong>guarantee of the once</strong>: <code>Entry</code> and <code>Leave</code> run once per transition, the events are not duplicated,</li>
<li class="">a <strong>place for everything</strong>: a new requirement (a double click) is a new state or a new row in the table, and not an edit of three nested conditions,</li>
<li class="">a <strong>machine that can be tested on a PC</strong> with a string as the input, as you have just seen.</li>
</ul>
<p><strong>It costs:</strong></p>
<ul>
<li class="">the <strong>boilerplate</strong>: four functions per state, most of them empty. It is a price for the uniformity, and it pays off with the 5th state. For a machine with two states, a <code>switch</code> is better,</li>
<li class="">the <strong>table of the transitions has to be thought through</strong> before you write code. That is not a cost, but it feels like one at the beginning.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pitfalls">Pitfalls<a href="https://embedbits.cz/blog/fsm-in-practice-button#pitfalls" class="hash-link" aria-label="Direct link to Pitfalls" title="Direct link to Pitfalls" translate="no">​</a></h2>
<ol>
<li class=""><strong>Time belongs to the task period, not to a delay.</strong> The machine counts the runs, so the limits (50 ms, 1 s) are the numbers of the ticks. Never call a delay in a state, it blocks all the other machines.</li>
<li class=""><strong>Sample in the task, not in the interrupt.</strong> The interrupt of the pin would see every bounce. The task that runs every 10 ms is a low-pass filter for free.</li>
<li class=""><strong>A single event slot loses events</strong> if the application reads it slower than the machine produces it. For a button it does not matter, for a protocol it does: use a queue.</li>
<li class=""><strong>The invalid state is a state.</strong> The check of the range in the core sends a corrupted variable to the safe state instead of reading the table outside of its bounds (the MISRA rules about the <a class="" href="https://embedbits.cz/blog/misra-c-rules-in-practice">undefined behavior</a> apply here).</li>
<li class=""><strong>A state machine with 30 states is a sign of a missing hierarchy.</strong> Split it into several machines, where one is a <em>state</em> of another, and keep every one of them small enough to fit into a table on a single screen.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="corrections-in-the-template">Corrections in the template<a href="https://embedbits.cz/blog/fsm-in-practice-button#corrections-in-the-template" class="hash-link" aria-label="Direct link to Corrections in the template" title="Direct link to Corrections in the template" translate="no">​</a></h2>
<p>When I compared the example with the template from the first article, I found two slips in the template and I fixed them there (a later review of the template found more, see <a class="" href="https://embedbits.cz/blog/finite-state-machines#what-was-fixed">the list of the fixes</a>): the initial value of the state variables was a leftover name from another project (<code>APPCORE_HANDLER_STATE_1</code> instead of <code>&lt;MODULE&gt;_STATE_1</code>), and the last row of the table used <code>State_2_Leave</code> instead of <code>State_3_Leave</code>. The second one is the type of a bug that this article is about: the code compiles, and the machine calls the wrong routine on the exit of the third state. The table with the designated initializers makes it a bit harder to do, and a test that goes through all the states makes it impossible.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="Architecture" term="Architecture"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[One BSP, many STM32 families: why Git branches, and what they cost]]></title>
        <id>https://embedbits.cz/blog/bsp-stm32-families-git-branches</id>
        <link href="https://embedbits.cz/blog/bsp-stm32-families-git-branches"/>
        <updated>2026-10-05T18:00:00.000Z</updated>
        <summary type="html"><![CDATA[STM32 is not one microcontroller, it is a dozen families: the G4, the H5, the U5, the F4 and so on. They have the same Cortex-M core, but different peripherals, different register names and a different vendor driver package. If you want one firmware architecture to run on all of them, you have to decide where the differences live. There is no free option, and this article describes the one that I chose for the Embedbits BSP, what the numbers from the real repositories say about it, and what it costs.]]></summary>
        <content type="html"><![CDATA[<p>STM32 is not one microcontroller, it is a dozen families: the G4, the H5, the U5, the F4 and so on. They have the same Cortex-M core, but different peripherals, different register names and a different vendor driver package. If you want one firmware architecture to run on all of them, you have to decide where the differences live. There is no free option, and this article describes the one that I chose for the Embedbits BSP, what the numbers from the real repositories say about it, and what it costs.</p>
<!-- -->
<p>All the numbers below are from the repositories on 5 October 2026, measured with a small script that you will find at the end of the section about the costs. A word about the date: at that moment <strong>STM32F4 is the only family with a complete release</strong> of the BSP, and the release of the others (U5 first) was just being done. So the numbers show a platform in the middle of a migration, not the final state, and that is what makes them interesting. Run the script again after the release and compare.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="four-ways-to-support-many-families">Four ways to support many families<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#four-ways-to-support-many-families" class="hash-link" aria-label="Direct link to Four ways to support many families" title="Direct link to Four ways to support many families" translate="no">​</a></h2>






























<table><thead><tr><th>Approach</th><th>How it looks</th><th>Problem</th></tr></thead><tbody><tr><td><strong>One tree, <code>#ifdef</code></strong></td><td><code>#if defined(STM32G4) ... #elif defined(STM32U5) ...</code> in the code</td><td>The code fills with the conditions, most of it is dead for any given build (see the rules about dead code in the article about <a class="" href="https://embedbits.cz/blog/misra-c-rules-in-practice">MISRA</a>), and nobody dares to touch it</td></tr><tr><td><strong>Copy and paste</strong></td><td>A folder per family, a copy of everything</td><td>Every fix has to be done N times, by hand, and one of them is forgotten</td></tr><tr><td><strong>One repository per family</strong></td><td><code>Bsp-G4</code>, <code>Bsp-U5</code>, ...</td><td>The same as the copy, only with more repositories</td></tr><tr><td><strong>Abstraction + a branch per family</strong></td><td>One interface, the family lives in a branch</td><td>A branch can drift away from the others (see below)</td></tr></tbody></table>
<p>I use the last one. The idea is that the user selects the family <strong>once</strong>, and from then on the tree contains only the code of that family.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works-in-the-bsp">How it works in the BSP<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#how-it-works-in-the-bsp" class="hash-link" aria-label="Direct link to How it works in the BSP" title="Direct link to How it works in the BSP" translate="no">​</a></h2>
<p>Each STM32 family is a <strong>Git branch</strong> of the BSP repository (<code>STM32G4</code>, <code>STM32H5</code>, <code>STM32U5</code>, ...). The same is true for the modules of the BSP: the MCAL modules, the linker and the RAL. The platform does the rest. When you run the setup script of EmBi_Platform and choose <em>Configure BSP module</em>, it lists the branches:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Available BSP Families:</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">[0]: STM32G4</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">[1]: STM32G4_Dev</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">[2]: STM32H5</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">[3]: STM32H5_Dev</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">[4]: STM32U5</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">[5]: master</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Enter branch ID (numerical):</span><br></div></code></pre></div></div>
<p>and after your choice it adds the BSP modules as Git submodules, checks out the branch and the commits of the family, and updates the CMake files. A project is pinned to the exact commits, so it builds the same tomorrow. The entries with <code>_Dev</code> are the development branches of the family and <code>master</code> contains the latest unreleased changes of all families, so it is meant for the work on the platform and not for a product. Switching to another family means running the same option again.</p>
<p>The vendor driver package follows the same scheme. The RAL has branches <code>STM32&lt;family&gt;</code> for the family, <code>STM32&lt;family&gt;_&lt;major&gt;.x</code> for a major release of the ST drivers and <code>STM32&lt;family&gt;_&lt;major&gt;.&lt;minor&gt;</code> for a minor one. When ST publishes a new version, there is a new branch and the old one stays available for the projects that use it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-the-differences-really-are">Where the differences really are<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#where-the-differences-really-are" class="hash-link" aria-label="Direct link to Where the differences really are" title="Direct link to Where the differences really are" translate="no">​</a></h2>
<p>I wanted to know how much of the code is actually different between the families, so I compared the branches. Here is the GPIO module, <code>Bsp-Mcal-Gpio</code>, with the released STM32F4 as the reference. The numbers are the changed lines (added plus removed) in each file:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">file               STM32F4 vs STM32G4   STM32F4 vs STM32H5   STM32F4 vs STM32U5</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Gpio.c             306                  142                  303</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Gpio.h             5                    0                    0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Gpio_Port.h        3                    0                    0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Gpio_Types.h       35                   5                    28</span><br></div></code></pre></div></div>
<p>The public interface, <code>Gpio_Port.h</code>, is <strong>identical</strong> on the F4 and the H5 and differs in three lines of a comment on the G4 and the U5. The G4 and the U5 are close to each other (their <code>Gpio.c</code> differs in three lines, again only a comment): they are the older generation of the module that is waiting for the release. Why is the <em>code of the module</em> so similar across two different families? Because the difference was moved out of the module, to the lowest layer. The RAL has a <code>Port</code> folder with one header for every peripheral, and the whole difference between the families in <code>Stm32_gpio.h</code> is this:</p>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token deleted-sign deleted prefix deleted" style="color:rgb(255, 85, 114)">-</span><span class="token deleted-sign deleted line" style="color:rgb(255, 85, 114)">#include "stm32g4xx_ll_gpio.h"              /* GPIO peripheral access layer   */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token deleted-sign deleted line" style="color:rgb(255, 85, 114)"></span><span class="token inserted-sign inserted prefix inserted" style="color:rgb(195, 232, 141)">+</span><span class="token inserted-sign inserted line" style="color:rgb(195, 232, 141)">#include "stm32u5xx_ll_gpio.h"              /* GPIO peripheral access layer   */</span><br></div></code></pre></div></div>
<p>One line. The MCAL module includes <code>Stm32_gpio.h</code> and never knows which vendor driver is behind it. The same is true for the other peripherals I compared between the G4 and the U5 (<code>Stm32_rcc.h</code>, <code>Stm32_usart.h</code>, <code>Stm32_tim.h</code>): two differing lines in 32. That is the whole idea of a layered architecture, applied to the question of the families.</p>
<p>What does differ are the <strong>sets of peripherals</strong>. The <code>Port</code> folder of the G4 has headers for the HRTIM and the DMAMUX, which the U5 does not have, and the U5 has the caches, the PKA, the SDMMC and the low-power GPIO, which the G4 does not have. A module for a peripheral that a family does not have is simply not present in its branch, and that is where the <em>family support</em> table on the page about the <a class="" href="https://embedbits.cz/docs/bsp/mcal">MCAL</a> comes from.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-levels-the-family-and-the-mcu">Two levels: the family and the MCU<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#two-levels-the-family-and-the-mcu" class="hash-link" aria-label="Direct link to Two levels: the family and the MCU" title="Direct link to Two levels: the family and the MCU" translate="no">​</a></h3>
<p>A branch handles the difference between the <em>families</em>. There is a smaller difference <em>inside</em> a family: the individual MCUs have a different number of the ports (an MCU in a small package has fewer GPIO ports than the one in a big package). That one is solved by a condition on the macros that the device header of the vendor already defines, not by a branch:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortConfig_t</span><span class="token plain">      gpio_PeriphConf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"> GPIO_PORT_CNT </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">if</span><span class="token macro property"> </span><span class="token macro property expression function" style="color:rgb(130, 170, 255)">defined</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">GPIOA</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">GpioReg </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIOA</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">GpioRcc </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> RCC_PERIPH_GPIOA </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ... */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">if</span><span class="token macro property"> </span><span class="token macro property expression function" style="color:rgb(130, 170, 255)">defined</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">GPIOJ</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">GpioReg </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIOJ</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">GpioRcc </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> RCC_PERIPH_GPIOJ </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">if</span><span class="token macro property"> </span><span class="token macro property expression function" style="color:rgb(130, 170, 255)">defined</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">GPIOK</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">GpioReg </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIOK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">GpioRcc </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> RCC_PERIPH_GPIOK </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>and, in the types, a port that does not exist is mapped to the value <code>GPIO_PORT_CNT</code>, so the other modules still compile and the use of such a port can be recognized as an invalid one. The rule: <strong>a branch for a different family, <code>#if defined</code> of the vendor's macro for a different MCU in the same family.</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-get">What you get<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#what-you-get" class="hash-link" aria-label="Direct link to What you get" title="Direct link to What you get" translate="no">​</a></h2>
<ul>
<li class=""><strong>The code of the family only.</strong> There are no <code>#ifdef</code> forests, nothing is dead, and the diff of a change shows only the code that is built.</li>
<li class=""><strong>A clean separation of the vendor code.</strong> The drivers of ST for each family are mirrored in their own branches of the RAL, and they are not modified. Your code does not contain them.</li>
<li class=""><strong>A stable interface for the application.</strong> The application calls <code>Gpio_Set_PinLevel()</code>, and it does not know the family, so a change of the MCU is a different branch and not a rewrite of the application.</li>
<li class=""><strong>The pinned versions.</strong> The project says exactly which commit of which branch it uses, so an update is a conscious decision.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-costs-the-drift">What it costs: the drift<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#what-it-costs-the-drift" class="hash-link" aria-label="Direct link to What it costs: the drift" title="Direct link to What it costs: the drift" translate="no">​</a></h2>
<p>The weakness of the branches is that they live their own lives. A fix that is done in one branch is not in the others, unless somebody takes it there. The measurement above shows two <em>generations</em> of the same module at the same time. The released F4 (and the H5, which follows it) has a refined initialization of the GPIO (the output level is set <em>before</em> the pin mode is switched to output, so the pin does not glitch), documented parameters and a <code>Tests</code> folder with the <strong>unit tests and the integration tests</strong>. The G4 and the U5 do not have any of that yet. The public interface of the USART in <code>Usart_Port.h</code> shows it even better:</p>






























<table><thead><tr><th>Branch</th><th>Public functions</th><th>Compared to the F4</th></tr></thead><tbody><tr><td>STM32F4 (released)</td><td>79</td><td>the reference</td></tr><tr><td>STM32H5</td><td>79</td><td>the same set of functions, the header differs in 2 lines</td></tr><tr><td>STM32G4</td><td>82</td><td>12 functions that the F4 does not have (<code>Usart_StartTransmit</code>, <code>Usart_Set_TransmitBytes</code>, ...) and 9 that it has and the G4 does not (<code>Usart_Set_TxStart</code>, <code>Usart_Set_DataConfig</code>, ...)</td></tr><tr><td>STM32U5</td><td>83</td><td>13 functions only on the U5, 9 only on the F4</td></tr></tbody></table>
<p>At this moment, a code that is written against the interface of the F4 compiles on the H5 and does not compile on the G4 and the U5. This is not a flaw of the approach, it is the normal state of a platform in the middle of a release. But it shows the price: the promise "the same BSP interface for all families" is true for a family only <strong>after its branch has been released</strong>, and the time between the release of the first family and of the last one is the period in which the branches drift away from each other. During it nobody should write an application for the family that is not ready.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-keep-the-drift-under-control">How to keep the drift under control<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#how-to-keep-the-drift-under-control" class="hash-link" aria-label="Direct link to How to keep the drift under control" title="Direct link to How to keep the drift under control" translate="no">​</a></h3>
<ol>
<li class=""><strong>Have a reference branch and a list of what is ported.</strong> One family leads (here the F4), the others follow, and the status is visible: that is the table of the family support on the MCAL page, extended with "the same version of the interface as the reference".</li>
<li class=""><strong>Make the release one operation.</strong> A release script that goes through all the modules of one family (the way the U5 release is being done) is better than a hand-made merge: the family is either ready as a whole, or it is not.</li>
<li class=""><strong>Measure the drift.</strong> The script below compares one module on several branches and prints the number of the changed lines per file. Zero or a comment means "the same", a big number is the work that is waiting. It takes a second and fits into a CI job.</li>
<li class=""><strong>Let one test suite check all branches.</strong> The unit tests that exist on the F4 (and the H5) are the specification of the module. If the same <code>Test_Gpio.c</code> has to pass on every family branch, the interface cannot silently diverge. The article about the <a class="" href="https://embedbits.cz/blog/unit-testing-unity-cmock">unit testing</a> shows how such a test is built.</li>
<li class=""><strong>Keep the difference at the bottom.</strong> Everything that can be moved to the <code>Port</code> headers of the RAL (a single <code>#include</code>, as shown above) is a difference that does not need to be maintained per branch. The more code is <em>identical</em>, the easier it is to take a fix from one branch to another (<code>git cherry-pick</code>).</li>
</ol>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">branch-drift.sh</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token shebang important">#!/usr/bin/env bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Shows how much a module differs between its family branches.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Usage: branch-drift.sh &lt;repository-url&gt; &lt;branch&gt; &lt;branch&gt; [&lt;branch&gt;...]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-euo</span><span class="token plain"> pipefail</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">repo</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$1</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">shift</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">branches</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$@</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">work</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$(</span><span class="token string variable" style="color:rgb(191, 199, 213)">mktemp </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-d</span><span class="token string variable" style="color:rgb(191, 199, 213)">)</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">git</span><span class="token plain"> init </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-q</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">git</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-C</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> remote </span><span class="token function" style="color:rgb(130, 170, 255)">add</span><span class="token plain"> origin </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$repo</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token for-or-select variable" style="color:rgb(191, 199, 213)">branch</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">${branches</span><span class="token string variable punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string variable" style="color:rgb(191, 199, 213)">@</span><span class="token string variable punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token string variable" style="color:rgb(191, 199, 213)">}</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">git</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-C</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> fetch </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-q</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">--depth</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token plain"> origin </span><span class="token string" style="color:rgb(195, 232, 141)">"refs/heads/</span><span class="token string variable" style="color:rgb(191, 199, 213)">$branch</span><span class="token string" style="color:rgb(195, 232, 141)">:refs/remotes/origin/</span><span class="token string variable" style="color:rgb(191, 199, 213)">$branch</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">files</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$(</span><span class="token string variable function" style="color:rgb(130, 170, 255)">git</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-C</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> ls-tree </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-r</span><span class="token string variable" style="color:rgb(191, 199, 213)"> --name-only </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"origin/</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">${branches</span><span class="token string variable string variable punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">0</span><span class="token string variable string variable punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">}</span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable operator" style="color:rgb(137, 221, 255)">|</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable function" style="color:rgb(130, 170, 255)">grep</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-E</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable string" style="color:rgb(195, 232, 141)">'\.(c|h)$'</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable operator" style="color:rgb(137, 221, 255)">||</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable boolean" style="color:rgb(255, 88, 116)">true</span><span class="token string variable" style="color:rgb(191, 199, 213)">)</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">printf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'%-44s'</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"file"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">((</span><span class="token variable" style="color:rgb(191, 199, 213)">i </span><span class="token variable operator" style="color:rgb(137, 221, 255)">=</span><span class="token variable" style="color:rgb(191, 199, 213)"> </span><span class="token variable number" style="color:rgb(247, 140, 108)">1</span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token variable" style="color:rgb(191, 199, 213)"> i </span><span class="token variable operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token variable" style="color:rgb(191, 199, 213)"> ${#branches[@]}</span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token variable" style="color:rgb(191, 199, 213)"> i</span><span class="token variable operator" style="color:rgb(137, 221, 255)">++</span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">))</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">do</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">printf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'%-24s'</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">${branches</span><span class="token string variable punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string variable" style="color:rgb(191, 199, 213)">0</span><span class="token string variable punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token string variable" style="color:rgb(191, 199, 213)">}</span><span class="token string" style="color:rgb(195, 232, 141)"> vs </span><span class="token string variable" style="color:rgb(191, 199, 213)">${branches</span><span class="token string variable punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string variable" style="color:rgb(191, 199, 213)">i</span><span class="token string variable punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token string variable" style="color:rgb(191, 199, 213)">}</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">printf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'\n'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token for-or-select variable" style="color:rgb(191, 199, 213)">file</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token variable" style="color:rgb(191, 199, 213)">$files</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">printf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'%-44s'</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$file</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">((</span><span class="token variable" style="color:rgb(191, 199, 213)">i </span><span class="token variable operator" style="color:rgb(137, 221, 255)">=</span><span class="token variable" style="color:rgb(191, 199, 213)"> </span><span class="token variable number" style="color:rgb(247, 140, 108)">1</span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token variable" style="color:rgb(191, 199, 213)"> i </span><span class="token variable operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token variable" style="color:rgb(191, 199, 213)"> ${#branches[@]}</span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token variable" style="color:rgb(191, 199, 213)"> i</span><span class="token variable operator" style="color:rgb(137, 221, 255)">++</span><span class="token variable punctuation" style="color:rgb(199, 146, 234)">))</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">changed</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$(</span><span class="token string variable function" style="color:rgb(130, 170, 255)">git</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">-C</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable function" style="color:rgb(130, 170, 255)">diff</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable parameter variable" style="color:rgb(191, 199, 213)">--numstat</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"origin/</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">${branches</span><span class="token string variable string variable punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">0</span><span class="token string variable string variable punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">}</span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"origin/</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">${branches</span><span class="token string variable string variable punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">i</span><span class="token string variable string variable punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">}</span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> -- </span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable string variable" style="color:rgb(191, 199, 213)">$file</span><span class="token string variable string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable operator" style="color:rgb(137, 221, 255)">|</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable function" style="color:rgb(130, 170, 255)">awk</span><span class="token string variable" style="color:rgb(191, 199, 213)"> </span><span class="token string variable string" style="color:rgb(195, 232, 141)">'{print $1 + $2}'</span><span class="token string variable" style="color:rgb(191, 199, 213)">)</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">printf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'%-24s'</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">${changed</span><span class="token string variable operator" style="color:rgb(137, 221, 255)">:-</span><span class="token string variable" style="color:rgb(191, 199, 213)">0}</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">printf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'\n'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-rf</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"</span><span class="token string variable" style="color:rgb(191, 199, 213)">$work</span><span class="token string" style="color:rgb(195, 232, 141)">"</span><br></div></code></pre></div></div>
<p>Used on the branches of the GPIO module (the table above is its output):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">./branch-drift.sh https://github.com/Embedbits/Bsp-Mcal-Gpio STM32F4 STM32G4 STM32H5 STM32U5</span><br></div></code></pre></div></div>
<p>For the other modules the picture is different, and that is useful to know before you plan the work:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">file             F4 vs G4   F4 vs H5   F4 vs U5</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Exti_Port.h      0          0          0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Exti.c           586        538        682</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Usart_Port.h     55         2          28</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Usart.c          3734       2301       3927</span><br></div></code></pre></div></div>
<p>The EXTI has an unchanged public header on all the branches and a different implementation (the peripherals differ, the interface does not). The USART differs in the interface of the G4 and the U5 and in a big part of the implementation, which is a measure of how much work the release of those two is.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="which-approach-to-choose">Which approach to choose<a href="https://embedbits.cz/blog/bsp-stm32-families-git-branches#which-approach-to-choose" class="hash-link" aria-label="Direct link to Which approach to choose" title="Direct link to Which approach to choose" translate="no">​</a></h2>
<ul>
<li class=""><strong>Branches per family</strong> fit when the families differ in the <em>set</em> of peripherals and in the vendor drivers, when the product is built for several families and when you can afford to maintain the interface (the drift is manageable with a few families and a tool).</li>
<li class=""><strong><code>#ifdef</code> in one tree</strong> is acceptable when the differences are small: one family with a few MCU variants, a single register that is named differently.</li>
<li class=""><strong>Neither of them</strong> helps without the <strong>abstraction at the bottom</strong>. The branch only decides which implementation of the interface is in the tree. If the application includes the vendor headers, a branch per family does not save you from anything.</li>
</ul>
<p>And whatever you choose, write down which family is the reference one and keep one number in a CI job: how far the others are.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="Architecture" term="Architecture"/>
        <category label="STM32" term="STM32"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[What happens before main(): reset, startup code and linker script]]></title>
        <id>https://embedbits.cz/blog/before-main-startup-linker</id>
        <link href="https://embedbits.cz/blog/before-main-startup-linker"/>
        <updated>2026-10-05T14:00:00.000Z</updated>
        <summary type="html"><![CDATA[Every C tutorial starts with int main(void). Nobody explains who calls it. And yet, when you write uint32_t counter = 5; as a global variable and the first line of main() reads 5, a lot of work already happened. When the work is not done, the symptom is a variable with a random value that "worked yesterday".]]></summary>
        <content type="html"><![CDATA[<p>Every C tutorial starts with <code>int main(void)</code>. Nobody explains who calls it. And yet, when you write <code>uint32_t counter = 5;</code> as a global variable and the first line of <code>main()</code> reads 5, a lot of work already happened. When the work is not done, the symptom is a variable with a random value that "worked yesterday".</p>
<p>In this article we follow the microcontroller from the reset to the first line of <code>main()</code>: what the hardware does by itself, what the linker script says and what the startup code has to do. It is the content of two modules of the Embedbits BSP (<a class="" href="https://embedbits.cz/docs/bsp/linker">Linker</a> and <a class="" href="https://embedbits.cz/docs/bsp/startup">Startup</a>), but the principle is the same on every Cortex-M. All code in the article was built with <code>arm-none-eabi-gcc</code> 13.2.1 and <strong>run</strong> in QEMU, on a model of an STM32F405 board, so the addresses and the outputs are real.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-c-language-expects">What the C language expects<a href="https://embedbits.cz/blog/before-main-startup-linker#what-the-c-language-expects" class="hash-link" aria-label="Direct link to What the C language expects" title="Direct link to What the C language expects" translate="no">​</a></h2>
<p>The C standard promises a few things about a program that the hardware does not know about:</p>
<ul>
<li class="">a global variable with an initializer (<code>uint32_t initializedValue = 0x12345678u;</code>) has this value at the start,</li>
<li class="">a global or <code>static</code> variable without an initializer is <strong>zero</strong>,</li>
<li class="">there is a stack and the function can use it,</li>
<li class="">the global C++ objects are constructed (and in C, the functions marked with <code>__attribute__((constructor))</code> run) before <code>main()</code>.</li>
</ul>
<p>The hardware gives you very little. After the reset a Cortex-M core does only two things: it reads <strong>the initial value of the stack pointer</strong> from the first word of the vector table and <strong>the address of the reset handler</strong> from the second one, and jumps there. Everything else is a job of the startup code, which is a part of <strong>your</strong> firmware.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-vector-table">The vector table<a href="https://embedbits.cz/blog/before-main-startup-linker#the-vector-table" class="hash-link" aria-label="Direct link to The vector table" title="Direct link to The vector table" translate="no">​</a></h2>
<p>The vector table is an array of addresses placed at the beginning of the flash (on an STM32 it is <code>0x08000000</code>, which is also visible at the address 0 after a boot from the flash). In the minimal form it has the stack pointer, the reset handler and the handlers of the exceptions:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">__attribute__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">section</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">".isr_vector"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> used</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> vectorTable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_estack</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* [0] initial stack pointer */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Reset_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">              </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* [1] where the core jumps after the reset */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    NMI_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    HardFault_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>This is what the first 16 bytes of the built firmware contain:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Contents of section .isr_vector:</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"> 8000000 00000220 13000008 11000008 11000008</span><br></div></code></pre></div></div>
<p>The numbers are in the little-endian order. The first word is <code>0x20020000</code>, the end of the 128 kB of RAM that starts at <code>0x20000000</code>, which is where the stack begins (it grows down). The second one is <code>0x08000013</code>: the reset handler is at <code>0x08000012</code> and the lowest bit says "Thumb code", which is mandatory on a Cortex-M. The rest are the exceptions; I pointed all unused ones to the same handler.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-linker-script-a-map-of-the-memory">The linker script: a map of the memory<a href="https://embedbits.cz/blog/before-main-startup-linker#the-linker-script-a-map-of-the-memory" class="hash-link" aria-label="Direct link to The linker script: a map of the memory" title="Direct link to The linker script: a map of the memory" translate="no">​</a></h2>
<p>The compiler produces the object files with the sections (<code>.text</code> for the code, <code>.data</code>, <code>.bss</code> and so on) and has no idea where in the memory they will be. That is decided by the linker, and it needs a map. This is the whole script of the example, 59 lines:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">link.ld</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">/* Entry point: the first instruction that runs after the reset */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ENTRY(Reset_Handler)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">MEMORY</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 1024K</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  RAM   (xrw) : ORIGIN = 0x20000000, LENGTH = 128K</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">/* The stack grows down from the end of the RAM */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">_estack = ORIGIN(RAM) + LENGTH(RAM);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">SECTIONS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  /* The vector table has to be at the very beginning of the flash */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  .isr_vector :</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    KEEP(*(.isr_vector))</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  } &gt; FLASH</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  .text :</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    *(.text*)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    *(.rodata*)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    . = ALIGN(4);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  } &gt; FLASH</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  /* Constructors of the C++ objects and functions marked as constructor */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  .init_array :</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    . = ALIGN(4);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    __init_array_start = .;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    KEEP(*(.init_array*))</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    __init_array_end = .;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  } &gt; FLASH</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  /* Start of the initial values of .data: in the flash, right after the code */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  _sidata = LOADADDR(.data);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  /* .data lives in the RAM (VMA), its initial values are stored in the flash (LMA) */</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  .data :</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    . = ALIGN(4);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _sdata = .;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    *(.data*)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    . = ALIGN(4);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _edata = .;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  } &gt; RAM AT &gt; FLASH</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  .bss (NOLOAD) :</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    . = ALIGN(4);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _sbss = .;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    *(.bss*)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    *(COMMON)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    . = ALIGN(4);</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _ebss = .;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  } &gt; RAM</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>Let us read the important parts.</p>
<p><strong><code>MEMORY</code></strong> describes the physical memories: where they start and how big they are. The attributes tell the linker what is allowed there (<code>rx</code>: read and execute, <code>xrw</code>: everything).</p>
<p><strong><code>.isr_vector</code> goes first</strong> into the flash, and <code>KEEP</code> prevents the linker from throwing it away: nothing in the code <em>calls</em> the table, so without <code>KEEP</code> it would look unused. <code>.text</code> follows with the code and the read-only data (<code>.rodata</code>, which means <code>const</code> variables stay in the flash and do not use any RAM).</p>
<p><strong><code>.data</code> is the interesting one.</strong> Look at the line <code>} &gt; RAM AT &gt; FLASH</code>. Each section has two addresses:</p>
<ul>
<li class="">the <strong>VMA</strong> (virtual memory address), where the section is when the program <em>runs</em>: <code>.data</code> has to be in the RAM, because it is written,</li>
<li class="">the <strong>LMA</strong> (load address), where the section is <em>stored</em> in the firmware image: the RAM is empty after a power-up, so the initial values must be somewhere that survives, the flash.</li>
</ul>
<p><code>arm-none-eabi-objdump -h</code> shows both:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Idx Name          Size      VMA       LMA       File off  Algn</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  0 .isr_vector   00000010  08000000  08000000  00001000  2**2</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  1 .text         000001b0  08000010  08000010  00001010  2**2</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  2 .init_array   00000004  080001c0  080001c0  000011c0  2**2</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  3 .data         00000004  20000000  080001c4  00002000  2**2</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  4 .bss          00000008  20000004  080001c8  00002004  2**2</span><br></div></code></pre></div></div>
<p><code>.data</code> lives at <code>0x20000000</code>, but its initial values are in the flash at <code>0x080001C4</code>. Somebody has to copy them, and that is why the script defines the symbols <code>_sidata</code> (the source in the flash), <code>_sdata</code> and <code>_edata</code> (the begin and the end of the target in the RAM). These symbols have no memory behind them, they are only addresses that the C code reads with <code>&amp;_sdata</code>:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">080001c4 A _sidata</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">20000000 D _sdata</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">20000004 D _edata</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">20000004 B _sbss</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">2000000c B _ebss</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">20020000 R _estack</span><br></div></code></pre></div></div>
<p><strong><code>.bss</code> is <code>NOLOAD</code>.</strong> It has no content in the image, only a size (a variable without an initializer and its zero value would waste the flash). The startup code has to fill the area between <code>_sbss</code> and <code>_ebss</code> with zeros.</p>
<p><strong><code>.init_array</code></strong> is a table of the pointers to the constructors. The startup code goes through it and calls them.</p>
<p>The linker script of the Embedbits BSP is generated for each MCU by CMake from a template. It has the same symbols (<code>_sidata</code>, <code>_sdata</code>, <code>_edata</code>, <code>_sbss</code>, <code>_ebss</code>, <code>_stack_top</code>) and also describes optional regions, such as the CCMRAM of the STM32G4, where a section <code>.ccmram</code> can be placed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-startup-code">The startup code<a href="https://embedbits.cz/blog/before-main-startup-linker#the-startup-code" class="hash-link" aria-label="Direct link to The startup code" title="Direct link to The startup code" translate="no">​</a></h2>
<p>The script said where everything is, and now the code does what the C language expects:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">startup.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Symbols created by the linker script */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">extern</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> _sidata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> _sdata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> _edata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> _sbss</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> _ebss</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> _estack</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">extern</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">__init_array_start</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">extern</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">__init_array_end</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Reset_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Default_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* A few of the exception handlers, all unused ones point to the default one */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">NMI_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">       </span><span class="token keyword" style="font-style:italic">__attribute__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">weak</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">alias</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"Default_Handler"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">HardFault_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">__attribute__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">weak</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">alias</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"Default_Handler"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The vector table: the first word is the initial stack pointer, the second the reset handler */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">__attribute__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">section</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">".isr_vector"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> used</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> vectorTable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_estack</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Reset_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    NMI_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    HardFault_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Reset_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifdef</span><span class="token macro property"> </span><span class="token macro property expression">DEMO_DIRTY_RAM</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Only for the demo: RAM full of garbage, as after a reset of a running system.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">     * The upper 4 kB are left alone, the stack of this function lives there. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">ramWord </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_sdata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> ramWord </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uintptr_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_estack </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0x1000u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> ramWord</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">ramWord </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0xA5A5A5A5u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">DEMO_SKIP_INIT</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 1. Copy the initial values of .data from the flash to the RAM */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">source </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_sidata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">target </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_sdata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> target </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_edata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">target</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">source</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 2. Zero the .bss */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">target </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_sbss</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> target </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">_ebss</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">target</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 3. Run the constructors */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">constructor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> __init_array_start</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> constructor </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> __init_array_end</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> constructor</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">constructor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 4. Hand over to the application */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Default_Handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The <code>Reset_Handler</code> has four steps (the <code>#ifdef</code> parts are for the experiment below):</p>
<ol>
<li class=""><strong>Copy <code>.data</code></strong> from the flash (<code>_sidata</code>) to the RAM (<code>_sdata</code> to <code>_edata</code>).</li>
<li class=""><strong>Zero <code>.bss</code></strong> (<code>_sbss</code> to <code>_ebss</code>).</li>
<li class=""><strong>Call the constructors</strong> from <code>.init_array</code>.</li>
<li class=""><strong>Call <code>main()</code></strong>. If it ever returns, the program stays in an infinite loop, because there is nobody to return to.</li>
</ol>
<p>In the Embedbits BSP the startup module does a bit more according to its documentation: it also sets up the clocks (RCC through the MCAL) and then calls <code>AppMain()</code>. A rule that follows from the order: <strong>anything that runs before the steps 1 and 2 must not touch a global variable</strong>, because its content is not valid yet. The setup of the clocks is a function that uses only the registers, or the compiler keeps its state in locals.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="an-experiment-what-happens-without-it">An experiment: what happens without it<a href="https://embedbits.cz/blog/before-main-startup-linker#an-experiment-what-happens-without-it" class="hash-link" aria-label="Direct link to An experiment: what happens without it" title="Direct link to An experiment: what happens without it" translate="no">​</a></h2>
<p>The application of the example has four global variables of four kinds:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">main.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> initializedValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0x12345678u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* .data: has a value in the flash */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> zeroedValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* .bss:  has to be zero            */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> constantValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0xC0FFEE00u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* .rodata: stays in the flash      */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> constructedValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* set by a constructor before main */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">__attribute__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">constructor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Construct</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    constructedValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0xC0DE0001u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"initializedValue"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> initializedValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"zeroedValue      "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> zeroedValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"constantValue    "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> constantValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"constructedValue "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> constructedValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"address of initializedValue"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">initializedValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">PrintHex</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"address of constantValue   "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">constantValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Quit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>(The part above this, with the functions that print through <em>semihosting</em>, is a few lines of code that ask QEMU to print a text and to quit. It is not important for the topic.)</p>
<p>First the normal build. The result:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">initializedValue 0x12345678</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">zeroedValue       0x00000000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">constantValue     0xC0FFEE00</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">constructedValue  0xC0DE0001</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">address of initializedValue 0x20000000</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">address of constantValue    0x080001BC</span><br></div></code></pre></div></div>
<p>All four values are as the C language promises, and the addresses confirm the story: the variable in the RAM is at <code>0x2000...</code>, the constant in the flash at <code>0x0800...</code>.</p>
<p>Now the experiment. After a reset of a running system, the RAM is not empty: it contains whatever was there before. The cold start of an MCU is often "lucky", because the RAM happens to be zero, and then a bug in the startup code is hidden for a long time. For the test I made the RAM dirty (<code>-DDEMO_DIRTY_RAM</code> fills it with <code>0xA5A5A5A5</code> before everything else) and then I removed the steps 1 and 2 (<code>-DDEMO_SKIP_INIT</code>):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">arm-none-eabi-gcc </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-mcpu</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">cortex-m4 </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-mthumb</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-Os</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-ffreestanding</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-nostartfiles</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-T</span><span class="token plain"> link.ld </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-DDEMO_DIRTY_RAM</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-DDEMO_SKIP_INIT</span><span class="token plain"> startup.c main.c </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-o</span><span class="token plain"> broken.elf</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">qemu-system-arm </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-M</span><span class="token plain"> netduinoplus2 </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-nographic</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    -semihosting-config </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">enable</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">on,target</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">native </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-kernel</span><span class="token plain"> broken.elf</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">initializedValue 0xA5A5A5A5</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">zeroedValue       0xA5A5A5A5</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">constantValue     0xC0FFEE00</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">constructedValue  0xC0DE0001</span><br></div></code></pre></div></div>
<p>Look at what is wrong and what is not:</p>
<ul>
<li class=""><code>initializedValue</code> and <code>zeroedValue</code> are garbage. The first one has no initial value, the second one is not zero, although both lines in the C file say otherwise.</li>
<li class=""><code>constantValue</code> is fine, because it is in the flash and nobody needs to copy it.</li>
<li class=""><code>constructedValue</code> is fine, because the constructor wrote it <em>after</em> the (missing) initialization. This is why this kind of the bug is so hard to find: one half of the program works, and the other half has random values.</li>
</ul>
<p>With the dirty RAM and the complete startup code, the same program prints the correct values again.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-looks-in-real-life">How it looks in real life<a href="https://embedbits.cz/blog/before-main-startup-linker#how-it-looks-in-real-life" class="hash-link" aria-label="Direct link to How it looks in real life" title="Direct link to How it looks in real life" translate="no">​</a></h2>
<p>A few symptoms and what usually stands behind them:</p>





























<table><thead><tr><th>Symptom</th><th>Likely cause</th></tr></thead><tbody><tr><td>The program hard-faults immediately after the reset</td><td>The first word of the vector table is not a valid stack address (wrong <code>_estack</code>, a wrong RAM size), or the table is not at the start of the flash</td></tr><tr><td>A global with an initializer has a wrong value, one with <code>= 0</code> also</td><td><code>.data</code> is not copied or <code>.bss</code> is not zeroed (a wrong symbol, a section that is missing in the script)</td></tr><tr><td>It works after a power-up and fails after a reset</td><td>The same, the RAM was accidentally empty at the power-up</td></tr><tr><td>A strange value, which changes with the size of the code</td><td>The stack grows down to <code>.bss</code> / <code>.data</code>, the stack overflow</td></tr><tr><td>The first <code>printf</code> or a driver does not work</td><td>A code that runs before the steps 1 and 2 uses a global variable</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-numbers-of-the-tool-tell-you">What the numbers of the tool tell you<a href="https://embedbits.cz/blog/before-main-startup-linker#what-the-numbers-of-the-tool-tell-you" class="hash-link" aria-label="Direct link to What the numbers of the tool tell you" title="Direct link to What the numbers of the tool tell you" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">   text	   data	    bss	    dec	    hex	filename</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    448	      8	      8	    464	    1d0	good.elf</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Flash</strong> = <code>text</code> + <code>data</code>. The initial values of <code>.data</code> take space in the flash too, so a big initialized array costs you twice: in the flash and in the RAM. An array that does not change should be <code>const</code>, and then it is only in the flash.</li>
<li class=""><strong>RAM</strong> = <code>data</code> + <code>bss</code> (+ the stack and the heap).</li>
</ul>
<p>The linker can also check it for you, <code>-Wl,--print-memory-usage</code> prints how much of each region is used:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Memory region         Used Size  Region Size  %age Used</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">           FLASH:         456 B         1 MB      0.04%</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">             RAM:          12 B       128 KB      0.01%</span><br></div></code></pre></div></div>
<p>Put this flag into your build, and read the <code>.map</code> file (<code>-Wl,-Map,out.map</code>) when something is in an unexpected place: it contains the address of every function and every variable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://embedbits.cz/blog/before-main-startup-linker#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<ol>
<li class="">After the reset the core reads two words: the stack pointer and the address of the reset handler. Everything else is your code.</li>
<li class="">The <strong>linker script</strong> is the map: where the memories are, in what order the sections lie and which symbols mark their boundaries.</li>
<li class="">The <strong>startup code</strong> is what makes the language promises true: it copies <code>.data</code>, zeroes <code>.bss</code>, runs the constructors and calls <code>main()</code>.</li>
<li class="">A variable that has a value in the flash and lives in the RAM has two addresses, the load address and the run address. This is the key to the whole topic.</li>
<li class="">Keep <code>-Wl,--print-memory-usage</code> on, and read <code>arm-none-eabi-size</code> and the map file. They tell you more than the debugger about where your memory went.</li>
</ol>
<p>In the Embedbits BSP, you do not write these two files yourself: the linker script is generated for the selected MCU and the startup code comes with the BSP branch of the family. It is still worth understanding what they do, because when the firmware does not start, nobody else can help you.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="STM32" term="STM32"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Unit testing embedded C on your PC with Unity and CMock]]></title>
        <id>https://embedbits.cz/blog/unit-testing-unity-cmock</id>
        <link href="https://embedbits.cz/blog/unit-testing-unity-cmock"/>
        <updated>2026-10-05T10:00:00.000Z</updated>
        <summary type="html"><![CDATA["Embedded software cannot be unit tested, you need the hardware." I hear it often, and it is true for exactly one kind of code: the code that touches the registers. All the rest, the state machines, the protocol parsers, the control logic, the conversion of the values, is plain C that compiles on your PC. And on your PC it runs in milliseconds, without a debugger, without a cable and without flashing.]]></summary>
        <content type="html"><![CDATA[<p>"Embedded software cannot be unit tested, you need the hardware." I hear it often, and it is true for exactly one kind of code: the code that touches the registers. All the rest, the state machines, the protocol parsers, the control logic, the conversion of the values, is plain C that compiles on your PC. And on your PC it runs in milliseconds, without a debugger, without a cable and without flashing.</p>
<p>This article shows how to test a module with <a href="https://github.com/ThrowTheSwitch/Unity" target="_blank" rel="noopener noreferrer" class="">Unity</a> (the test framework) and <a href="https://github.com/ThrowTheSwitch/CMock" target="_blank" rel="noopener noreferrer" class="">CMock</a> (the generator of mocks), from the design that makes it possible to the CMake file that builds it. Everything was built and run, and the output below is the real one.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-need-to-test-and-what-you-need-to-remove">What you need to test, and what you need to remove<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#what-you-need-to-test-and-what-you-need-to-remove" class="hash-link" aria-label="Direct link to What you need to test, and what you need to remove" title="Direct link to What you need to test, and what you need to remove" translate="no">​</a></h2>
<p>A unit test runs one module in isolation. The module under test calls the lower layer (the BSP, a driver, another module), and <strong>that</strong> is the problem: the lower layer needs hardware. The solution is not to give the module a simulated hardware, but to replace the whole lower layer with something the test controls. That something is a <strong>mock</strong>: a function with the same signature as the real one, which does not do anything real. It only remembers how it was called and returns what the test told it to return.</p>
<p>This works only if the module has a place where the lower layer can be replaced. In the article about <a class="" href="https://embedbits.cz/blog/solid-principles-c-cpp">SOLID principles</a> there was the <em>link-time injection</em>: the module calls a function that is declared in a header (<code>Bsp_Thermostat.h</code>), and the build system decides which source file implements it. On the target it is the real BSP, in the unit test it is the mock. This is the same principle as the architecture from the article about <a class="" href="https://embedbits.cz/blog/design-architecture">design and architecture</a>: when the layers have clean interfaces, every layer can be tested without the layers below.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-tools">The tools<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#the-tools" class="hash-link" aria-label="Direct link to The tools" title="Direct link to The tools" translate="no">​</a></h2>
<ul>
<li class=""><strong>Unity</strong> is a framework with assertions (<code>TEST_ASSERT_TRUE</code>, <code>TEST_ASSERT_EQUAL_UINT8</code>, <code>TEST_ASSERT_EQUAL_FLOAT</code>, <code>TEST_ASSERT_EQUAL_MEMORY</code> and many more) and a small script that generates the <code>main()</code> with the list of the tests from your test file, so you never have to register a test by hand. It is a few C files that are compiled together with the test.</li>
<li class=""><strong>CMock</strong> reads a header file and generates the mock of every function in it: <code>MockBsp_Thermostat.c/.h</code>. It is written in Ruby, but only the <em>generator</em> is, the generated mock is plain C.</li>
<li class=""><strong>Ruby</strong> is needed for the two generators, which run at build time. It does not end up in the tested code.</li>
</ul>
<p>In the Embedbits platform these three are artifacts (<code>unity</code>, <code>cmock</code> and <code>ruby</code>), so the project does not depend on what is installed on the PC of the developer. The versions are in <code>ArtifactsConfig.txt</code> (the syntax is <code>&lt;artifact_name&gt;;&lt;binary_version&gt;;&lt;handler_version&gt;</code>). In this article I used Unity 2.6.1 and CMock 2.6.0 with plain CMake, so that the example works everywhere.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-module-under-test">The module under test<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#the-module-under-test" class="hash-link" aria-label="Direct link to The module under test" title="Direct link to The module under test" translate="no">​</a></h2>
<p>A thermostat with a hysteresis. It reads the temperature from the BSP and switches a heater on below 20 °C and off above 22 °C. If the sensor does not answer, it switches the heater off, because a heater without a measurement is a fire. The interface to the hardware is a header with two functions:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Bsp_Thermostat.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">BSP_THERMOSTAT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">BSP_THERMOSTAT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Implemented by the BSP of the board - or mocked in the unit test. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Returns false if the sensor does not answer, the value is then not valid. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<p>The public port of the module and its implementation:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Thermostat_Port.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">THERMOSTAT_THERMOSTAT_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">THERMOSTAT_THERMOSTAT_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Is_HeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Thermostat.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Thermostat_Port.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Bsp_Thermostat.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">THERMOSTAT_SWITCH_ON_CELSIUS</span><span class="token macro property">   </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">20.0f</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">THERMOSTAT_SWITCH_OFF_CELSIUS</span><span class="token macro property">  </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">22.0f</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> bool isHeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    isHeaterOn </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* fail safe: no value, no heating */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> THERMOSTAT_SWITCH_ON_CELSIUS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> THERMOSTAT_SWITCH_OFF_CELSIUS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* inside the hysteresis band: keep the current state */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Is_HeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> isHeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The module does not include any hardware header, it does not know STM32 and it can be compiled with the compiler of your PC. This is the first test of the design: if it does not compile, it is not separated enough.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-test">The test<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#the-test" class="hash-link" aria-label="Direct link to The test" title="Direct link to The test" translate="no">​</a></h2>
<p>The test file includes the header of the module under test and the header of the <strong>mock</strong>, which does not exist yet. It is generated from <code>Bsp_Thermostat.h</code> during the build.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">test_Thermostat.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"unity.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Thermostat_Port.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"MockBsp_Thermostat.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">setUp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater_Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">tearDown</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The mock reads this variable when Thermostat_Task() calls it, so it has to outlive the helper. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sensorCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Helper: the sensor answers with the given temperature. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Sensor_Returns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    sensorCelsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_Celsius_ExpectAnyArgsAndReturn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_Celsius_ReturnThruPtr_celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">sensorCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">test_HeaterSwitchesOnBelowLowerLimit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Sensor_Returns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">18.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater_Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">TEST_ASSERT_TRUE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Is_HeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">test_HeaterSwitchesOffAboveUpperLimit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Sensor_Returns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">18.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater_Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Sensor_Returns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">23.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater_Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">TEST_ASSERT_FALSE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Is_HeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">test_HeaterKeepsStateInsideHysteresis</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Sensor_Returns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">18.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater_Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Sensor_Returns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">21.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* no Bsp_Set_Heater expected: the mock fails the test if it is called */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">TEST_ASSERT_TRUE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Is_HeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">test_HeaterSwitchesOffWhenSensorFails</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Sensor_Returns</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">18.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater_Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_Celsius_ExpectAnyArgsAndReturn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater_Expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">TEST_ASSERT_FALSE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Is_HeaterOn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Let us read it from the top.</p>
<ul>
<li class=""><code>setUp()</code> is called by Unity before every test. The module keeps its state in a <code>static</code> variable, so each test starts with <code>Thermostat_Init()</code>, and <code>Bsp_Set_Heater_Expect(false)</code> tells the mock that the initialization switches the heater off. Without this reset the tests would depend on each other and on their order.</li>
<li class=""><code>Sensor_Returns()</code> is a helper that says "the next call of <code>Bsp_Get_Celsius()</code> returns <code>true</code> and sets the value to this temperature". <code>_ExpectAnyArgsAndReturn</code> means "I do not care about the pointer", and <code>_ReturnThruPtr_celsius</code> fills the output parameter.</li>
<li class="">Each test is a short story in three parts: the sensor says something, the module is run (<code>Thermostat_Task()</code>), the result is checked. The expectation <code>Bsp_Set_Heater_Expect(true)</code> is also an assertion: if the module calls the function with another value, or does not call it, the test fails.</li>
<li class="">The third test shows the strength of mocks. Inside the hysteresis band nothing is expected, and that is the assertion: the mock fails the test as soon as the module calls <code>Bsp_Set_Heater()</code>.</li>
</ul>
<p>A trap that is worth knowing: <code>_ReturnThruPtr_celsius(&amp;value)</code> does not copy the value in the moment of the call, it remembers the <strong>pointer</strong> and reads the value when the module calls the mock. If <code>value</code> is a local variable of the helper, it is gone by then. The first version of the example for this article had the helper written this way, and the result was four failed tests with a message that looks like a bug in the module:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_HeaterSwitchesOnBelowLowerLimit:FAIL: Expected 1 Was 0. Function Bsp_Set_Heater</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Argument on. Function called with unexpected argument value.</span><br></div></code></pre></div></div>
<p>The module was correct, the variable was garbage. That is why the example has the <code>static float sensorCelsius</code> with the comment.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-build">The build<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#the-build" class="hash-link" aria-label="Direct link to The build" title="Direct link to The build" translate="no">​</a></h2>
<p>Two generators and one executable. CMake runs the generators before the compilation, and a change of a header regenerates the mock:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">cmock.yml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token key atrule">:cmock</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">:mock_path</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> mocks</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">:plugins</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">ignore</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">expect_any_args</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">return_thru_ptr</span><br></div></code></pre></div></div>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">CMakeLists.txt</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">cmake_minimum_required</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token property">VERSION</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.19</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">project</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">ThermostatTests C</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">enable_testing</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">find_program</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">RUBY ruby REQUIRED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">UNITY_DIR  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/../unity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">CMOCK_DIR  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/../cmock</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">MOCK_DIR   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BINARY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/mocks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">TEST_NAME  test_Thermostat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># 1. mock of the BSP interface, generated from its header</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_custom_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    OUTPUT  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">MOCK_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/MockBsp_Thermostat.c </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">MOCK_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/MockBsp_Thermostat.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMAND </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">RUBY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">CMOCK_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/lib/cmock.rb -o</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/cmock.yml</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/src/Bsp_Thermostat.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">WORKING_DIRECTORY</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BINARY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">DEPENDS</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/src/Bsp_Thermostat.h </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/cmock.yml</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># 2. the test runner (main + list of the tests), generated from the test file</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_custom_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    OUTPUT  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BINARY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">_Runner.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMAND </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">RUBY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">UNITY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/auto/generate_test_runner.rb</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/test/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">.c </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BINARY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">_Runner.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">DEPENDS</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/test/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># 3. one test executable: the module under test + the mock + the test + the framework</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_executable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    src/Thermostat.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    test/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_BINARY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">_Runner.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">MOCK_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/MockBsp_Thermostat.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">UNITY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/src/unity.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">CMOCK_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/src/cmock.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">target_include_directories</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"> src </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">MOCK_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">UNITY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/src </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">CMOCK_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/src</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">target_compile_options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"> -Wall -Wextra</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_test</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token property">NAME</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> COMMAND </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">TEST_NAME</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>The configuration of CMock (<code>cmock.yml</code>) has only the list of the plugins: <code>ignore</code>, <code>expect_any_args</code> and <code>return_thru_ptr</code>, which give the <code>_Ignore</code>, <code>_ExpectAnyArgs</code> and <code>_ReturnThruPtr_</code> functions that the test above uses. The <code>mock_path</code> is relative to the folder where the generator runs, which is the build directory.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-S</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">.</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-B</span><span class="token plain"> build</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">cmake </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">--build</span><span class="token plain"> build</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">./build/test_Thermostat        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># or: ctest --test-dir build</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_Thermostat.c:26:test_HeaterSwitchesOnBelowLowerLimit:PASS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_Thermostat.c:36:test_HeaterSwitchesOffAboveUpperLimit:PASS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_Thermostat.c:49:test_HeaterKeepsStateInsideHysteresis:PASS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_Thermostat.c:61:test_HeaterSwitchesOffWhenSensorFails:PASS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">-----------------------</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">4 Tests 0 Failures 0 Ignored</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">OK</span><br></div></code></pre></div></div>
<p>Notice what is <em>not</em> in the executable: no startup code, no linker script, no HAL, no ST header. Only the module, the mock, the test and the framework. It builds in a couple of seconds and runs in milliseconds, so it can run on every save and on every commit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="does-the-test-really-test-something">Does the test really test something?<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#does-the-test-really-test-something" class="hash-link" aria-label="Direct link to Does the test really test something?" title="Direct link to Does the test really test something?" translate="no">​</a></h2>
<p>A test that cannot fail is worth nothing. The cheapest check is a <strong>mutation</strong>: break the code on purpose and see whether a test notices. I changed the upper limit from 22 °C to 20 °C, which removes the hysteresis:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_HeaterSwitchesOnBelowLowerLimit:PASS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_HeaterSwitchesOffAboveUpperLimit:PASS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_HeaterKeepsStateInsideHysteresis:FAIL:Function Bsp_Set_Heater.  Called more times than expected.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">test_HeaterSwitchesOffWhenSensorFails:PASS</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">4 Tests 1 Failures 0 Ignored</span><br></div></code></pre></div></div>
<p>The hysteresis test caught the bug, and the message says what happened: the module called <code>Bsp_Set_Heater()</code> when it should not. It is a good habit to do it once for every new test.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-to-mock-and-what-not">What to mock and what not<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#what-to-mock-and-what-not" class="hash-link" aria-label="Direct link to What to mock and what not" title="Direct link to What to mock and what not" translate="no">​</a></h2>
<ul>
<li class=""><strong>Mock the boundary of the module, not its insides.</strong> The mock replaces the interface of the lower layer (here <code>Bsp_Thermostat.h</code>). Do not mock your own helper functions in the same module: the test then describes how the code is written and breaks with every refactoring, even when the behavior is the same.</li>
<li class=""><strong>Test through the public port.</strong> The test includes <code>Thermostat_Port.h</code> and nothing else of the module. If you need the internal header to test something, it is a sign that the module has two responsibilities. Read the article about <a class="" href="https://embedbits.cz/blog/file-organization-embedded-c">file organization</a> for how the public and the internal files are separated.</li>
<li class=""><strong>One behavior, one test.</strong> The name says what is expected (<code>HeaterSwitchesOffWhenSensorFails</code>), so a red test tells you what is broken before you open it.</li>
<li class=""><strong>The same pattern works in every layer.</strong> A module of the application is tested with the mock of the BSP interface, a module of the MCAL with the mock of the RAL port. In every case the layer below is replaced and the layer under test is real.</li>
<li class=""><strong>Call order.</strong> CMock can check that the calls of different mocks happen in a given order (the option <code>:enforce_strict_ordering</code>). It is useful for initialization sequences, but use it only where the order is a requirement and not an accident of the implementation.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-host-test-cannot-tell-you">What the host test cannot tell you<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#what-the-host-test-cannot-tell-you" class="hash-link" aria-label="Direct link to What the host test cannot tell you" title="Direct link to What the host test cannot tell you" translate="no">​</a></h2>
<p>I do not want to sell the host tests as everything. They do not find:</p>
<ul>
<li class="">the <strong>timing</strong>, the interrupts and the race conditions between them,</li>
<li class="">the <strong>registers</strong>: that the pin really goes high, that the peripheral clock was switched on. That is the job of the code in the RAL and the MCAL and it needs a simulator or the real hardware,</li>
<li class="">the <strong>differences between the PC and the MCU</strong>: the width of <code>int</code>, the alignment, the optimizer of the target compiler. The tests on the PC show the logic is right, not that the firmware is.</li>
</ul>
<p>That is why the host tests are the bottom of the pyramid: many, fast, and they run on every commit. Above them are a simulator (for example Renode) and the hardware tests, which are fewer and slower and cover what the PC cannot.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://embedbits.cz/blog/unit-testing-unity-cmock#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<ol>
<li class="">Design the module so that everything under it is behind a header (the <em>seam</em>).</li>
<li class="">Let CMock generate the mock from that header, and Unity the runner from the test file.</li>
<li class="">Build one small executable for the PC: the module, the mock, the test, the framework.</li>
<li class="">Write the tests as stories: the mock says what the world looks like, the module acts, the assertion checks the result.</li>
<li class="">Break the code once on purpose to see that the test fails.</li>
</ol>
<p>The whole example is about 150 lines of code, and the next time somebody asks you whether the thermostat really switches the heater off when the sensor fails, you do not need a heater. You run <code>ctest</code>.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="Testing" term="Testing"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[File organization in embedded C: how a folder becomes a module]]></title>
        <id>https://embedbits.cz/blog/file-organization-embedded-c</id>
        <link href="https://embedbits.cz/blog/file-organization-embedded-c"/>
        <updated>2026-10-04T14:00:00.000Z</updated>
        <summary type="html"><![CDATA[My coding style says that file names start with the module name and that "the complete file organization is described elsewhere". This is the elsewhere.]]></summary>
        <content type="html"><![CDATA[<p>My <a class="" href="https://embedbits.cz/docs/platform/embi-platform/coding-style">coding style</a> says that file names start with the module name and that "the complete file organization is described elsewhere". This is the elsewhere.</p>
<p>C has no <code>private</code>, no namespaces and no packages. Once the code is split into files, the files and the build system are the <strong>only</strong> tools you have to say what belongs together, what is public and what is nobody else's business. So the file organization is not a matter of taste, it is a part of the design. This article describes how I organize an embedded project on three levels: the project, the module and the single file.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="level-1-the-project">Level 1: the project<a href="https://embedbits.cz/blog/file-organization-embedded-c#level-1-the-project" class="hash-link" aria-label="Direct link to Level 1: the project" title="Direct link to Level 1: the project" translate="no">​</a></h2>
<p>A project created with EmBi_Platform has the same layout every time:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Project_root/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── Application/          your application</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── AppMain/            entry point</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── AppCore/            top level logic</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── AppFun/             functionalities (high level logic)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── AppComp/            components (low level logic)</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   └── AppCom/             communication modules</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── Middlewares/          reusable software without hardware dependency</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── ThirdParty/         vendor sources, one Git submodule per component</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── &lt;Name&gt;/             your glue code and configuration of that component</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   └── Middlewares.cmake</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── Bsp/                  Board Support Package</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── Hal/  Mcal/  Ral/   the three abstraction layers</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   ├── Linker/  Startup/   linker script generator, startup code</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">│   └── Docs/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── EmBi_Platform/        build tooling (Git submodule), not part of the firmware</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── STM32CubeIDE/         generated IDE project</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── ArtifactsConfig.txt   versions of the build tools</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">└── CMakeLists.txt        project root build file</span><br></div></code></pre></div></div>
<p>Every folder answers one question, and the answer is the reason why the code lives there.</p>
<p><strong>Application</strong> is what makes the product different from every other product on the same MCU. It has its own inner layers, and their names are the levels of the "tree" from the <a class="" href="https://embedbits.cz/blog/design-architecture">article about architecture</a>: <code>AppMain</code> starts everything, <code>AppCore</code> is the top of the tree with the logic of the whole device, <code>AppFun</code> contains the individual functionalities, <code>AppComp</code> the low level components they are built from and <code>AppCom</code> the communication with the outside world. The calls go from the top to the bottom, never the other way.</p>
<p><strong>Middlewares</strong> have two places for every component, and this is on purpose. <code>ThirdParty/FreeRTOS</code> is the vendor code, checked out as a Git submodule in a version that you choose, and you <strong>never edit it</strong>. Everything that is yours (the port layer, the configuration) lives next to it in <code>Middlewares/FreeRTOS</code>, and it is not overwritten when you switch the vendor code to another version. When the vendor releases a fix, you update a submodule and not a patched copy.</p>
<p><strong>Bsp</strong> is described in the <a class="" href="https://embedbits.cz/docs/bsp">BSP documentation</a>, the short version is: <code>Ral</code> knows the registers, <code>Mcal</code> the peripherals and <code>Hal</code> the board. Each STM32 family has its own branch of the BSP, so the folders look the same for every MCU.</p>
<p><strong>EmBi_Platform</strong> and <strong>STM32CubeIDE</strong> are tools. They do not end up in the binary, and the IDE project is generated, so it can be thrown away and created again.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="level-2-the-module">Level 2: the module<a href="https://embedbits.cz/blog/file-organization-embedded-c#level-2-the-module" class="hash-link" aria-label="Direct link to Level 2: the module" title="Direct link to Level 2: the module" translate="no">​</a></h2>
<p>A module is a folder with a fixed set of files. You do not have to create them by hand, the platform generates them (see the end of the article), and the result looks like this:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Temperature/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── CMakeLists.txt</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── Temperature_Types.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── Temperature_Port.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── Temperature.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── Temperature.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">└── Temperature_Filter.c     (a component, see below)</span><br></div></code></pre></div></div>



































<table><thead><tr><th>File</th><th>Role</th><th>Who may include it</th></tr></thead><tbody><tr><td><code>Temperature_Types.h</code></td><td>Public types, enumerations and macros</td><td>everybody</td></tr><tr><td><code>Temperature_Port.h</code></td><td>Public functions: the <strong>only</strong> entry point of the module</td><td>everybody</td></tr><tr><td><code>Temperature.h</code></td><td>Internal types and functions shared by the files of the module</td><td>only the module itself</td></tr><tr><td><code>Temperature.c</code></td><td>Implementation</td><td>(a source file)</td></tr><tr><td><code>CMakeLists.txt</code></td><td>Creates the static library <code>Temperature_Lib</code></td><td>the build</td></tr></tbody></table>
<p>The idea is that a user of the module reads <strong>two</strong> files and nothing else. The first one are the types (the generated file also contains the version type and the usual enumerations for the request and function states, I trimmed it here to what the example needs):</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Temperature_Types.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \file Temperature_Types.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \ingroup Temperature</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Temperature module global types definition</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">TEMPERATURE_TEMPERATURE_TYPES_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">TEMPERATURE_TEMPERATURE_TYPES_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== INCLUDES ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== TYPEDEFS ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/** Temperature in tenths of a degree Celsius, 253 = 25.3 degC */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">int16_t</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/** Enumeration used to signal request processing state */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    TEMPERATURE_REQUEST_ERROR </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Processing request failed  */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    TEMPERATURE_REQUEST_OK          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**&lt; Processing request succeed */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_RequestState_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token macro property"> </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* TEMPERATURE_TEMPERATURE_TYPES_H */</span><br></div></code></pre></div></div>
<p>The second one is the port, which is the whole interface of the module. Everything that is not here does not exist for the others:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Temperature_Port.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \file Temperature_Port.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \ingroup Temperature</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Temperature module public functionality</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * The only header that other modules include.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">TEMPERATURE_TEMPERATURE_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">TEMPERATURE_TEMPERATURE_PORT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifdef</span><span class="token macro property"> </span><span class="token macro property expression">__cplusplus</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">extern</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"C"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== INCLUDES ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Temperature_Types.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ========================= EXPORTED FUNCTIONS ============================= */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">                       </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Init</span><span class="token plain">     </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">                       </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Task</span><span class="token plain">     </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_RequestState_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Get_Value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifdef</span><span class="token macro property"> </span><span class="token macro property expression">__cplusplus</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token macro property"> </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* TEMPERATURE_TEMPERATURE_PORT_H */</span><br></div></code></pre></div></div>
<p>The internal header has the data and the functions that the files of the module need to share, and that nobody outside should ever see:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Temperature.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \file Temperature.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \ingroup Temperature</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief Temperature module internal definitions, not visible outside of the module</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">TEMPERATURE_TEMPERATURE_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">TEMPERATURE_TEMPERATURE_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== INCLUDES ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Temperature_Types.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== TYPEDEFS ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> filteredValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    bool                isValid</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_State_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ========================= EXPORTED FUNCTIONS ============================= */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Shared by the files of this module only */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Filter_Apply</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> rawValue </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><span class="token macro property"> </span><span class="token macro property comment" style="color:rgb(105, 112, 152);font-style:italic">/* TEMPERATURE_TEMPERATURE_H */</span><br></div></code></pre></div></div>
<p>And the implementation uses all of it:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Temperature.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Temperature.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Temperature_Port.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_State_t</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">filteredValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">isValid       </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> rawValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">253</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* a real module reads it from the ADC */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">filteredValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Filter_Apply</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rawValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">isValid       </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_RequestState_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Get_Value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_RequestState_t</span><span class="token plain"> requestState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> TEMPERATURE_REQUEST_ERROR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">isValid</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">value </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">filteredValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        requestState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> TEMPERATURE_REQUEST_OK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> requestState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Notice that the state is <code>static</code> in the <code>.c</code> file. There is no global variable, so there is no <code>extern</code> (which my coding style prohibits). The only way to the data is the function <code>Temperature_Get_Value()</code>, a getter that also tells the caller whether the value is valid.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-build-system-makes-the-file-the-encapsulation">The build system makes the file the encapsulation<a href="https://embedbits.cz/blog/file-organization-embedded-c#the-build-system-makes-the-file-the-encapsulation" class="hash-link" aria-label="Direct link to The build system makes the file the encapsulation" title="Direct link to The build system makes the file the encapsulation" translate="no">​</a></h3>
<p>"Include only the port" would be just a wish if nothing enforced it. The <code>CMakeLists.txt</code> of every module does. It builds a static library and <strong>copies only the public headers</strong> to a separate folder in the build directory. That folder is the only one that the users of the library get on their include path:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">CMakeLists.txt</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Source files list for current library generation</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> Temperature_SourceFiles</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Temperature.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Temperature_Filter.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># List of public header files provided by the current library</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> Temperature_PublicHeaders</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Temperature_Types.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Temperature_Port.h</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Create library</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">add_library</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Temperature_Lib </span><span class="token namespace" style="color:rgb(178, 204, 214)">STATIC</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">Temperature_SourceFiles</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Set public headers directory path in build folder</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">PUBLIC_HEADERS_DIR </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/PublicHeaders</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">file</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">MAKE_DIRECTORY </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">PUBLIC_HEADERS_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Copy only the public headers there</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">foreach</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">PublicHeader IN LISTS Temperature_PublicHeaders</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">configure_file</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">PublicHeader</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">PUBLIC_HEADERS_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">PublicHeader</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        COPYONLY</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">endforeach</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Set include directories for the created target</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">target_include_directories</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> Temperature_Lib</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token namespace" style="color:rgb(178, 204, 214)">PUBLIC</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">$&lt;</span><span class="token plain">BUILD_INTERFACE:</span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token plain">PUBLIC_HEADERS_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token namespace" style="color:rgb(178, 204, 214)">PRIVATE</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token variable" style="color:rgb(191, 199, 213)">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>(This is a simplified version of the template that the platform generates, which also handles the dependencies between the libraries and the Doxygen paths.) Now the application only links <code>Temperature_Lib</code>:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">AppMain.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdio.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Temperature_Port.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> value </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">TEMPERATURE_REQUEST_OK </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Get_Value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">printf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"%d\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>I tried what happens if the application includes the internal header of the module, and the compiler says what you want it to say:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">AppMain_Cheat.c:1:10: fatal error: Temperature.h: No such file or directory</span><br></div></code></pre></div></div>
<p>The folder with the public headers in the build directory contains exactly two files: <code>Temperature_Port.h</code> and <code>Temperature_Types.h</code>.</p>
<p><strong>An honest warning:</strong> it is the protection of the build system, not of the language. If somebody writes <code>#include "../../Middlewares/Temperature/Temperature.h"</code>, it compiles without a complaint (I tried that too). The cure is cheap: reject relative paths with <code>..</code> in the includes in the CI.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(191, 199, 213)">-rEn</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'#include "[^"]*\.\./'</span><span class="token plain"> Application Middlewares/*/ </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">exit</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-the-module-grows-components">When the module grows: components<a href="https://embedbits.cz/blog/file-organization-embedded-c#when-the-module-grows-components" class="hash-link" aria-label="Direct link to When the module grows: components" title="Direct link to When the module grows: components" translate="no">​</a></h3>
<p>A module with a thousand lines in one file is the next problem. The answer is a <strong>component</strong>: another pair of files <code>Module_Component.c/.h</code> in the same folder. In the example above it is the filter:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Temperature_Filter.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Temperature.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> lastValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Temperature_Filter_Apply</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token plain"> rawValue </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    lastValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">temperature_Value_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">lastValue </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> rawValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> lastValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The component header is internal as well (it is not in the list of the public headers), so the component can be exchanged or split without anyone noticing. The user of the module still sees the same two files. The rule that the file name starts with the module name makes the component visible in every file list, and the function name <code>Temperature_Filter_Apply()</code> tells where to find it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="level-3-inside-a-file">Level 3: inside a file<a href="https://embedbits.cz/blog/file-organization-embedded-c#level-3-inside-a-file" class="hash-link" aria-label="Direct link to Level 3: inside a file" title="Direct link to Level 3: inside a file" translate="no">​</a></h2>
<p>Every <code>.c</code> and <code>.h</code> file generated by the platform has the same skeleton with a banner for each section, in the same order:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/**</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \author ...</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \file Temperature.c</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \ingroup Temperature</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * \brief ...</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== INCLUDES ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ============================== TYPEDEFS ================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ======================== FORWARD DECLARATIONS ============================ */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ========================== SYMBOLIC CONSTANTS ============================ */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* =============================== MACROS =================================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ========================== EXPORTED VARIABLES ============================ */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* =========================== LOCAL VARIABLES ============================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ========================= EXPORTED FUNCTIONS ============================= */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* =========================== LOCAL FUNCTIONS ============================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* =========================== INTERRUPT HANDLERS =========================== */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ================================ TASKS =================================== */</span><br></div></code></pre></div></div>
<p>It looks like a decoration, and it is a map. When you open a file that you have never seen, you know that the local variables are in the fifth section and the interrupt handlers in the tenth, and you do not have to read the file to find them. The headers have the same idea, wrapped in an include guard and in <code>extern "C"</code> for the C++ users:</p>
<ul>
<li class="">the guard has the form <code>MODULE_FILE_H</code>, for example <code>TEMPERATURE_TEMPERATURE_PORT_H</code>,</li>
<li class="">the Doxygen header (<code>\file</code>, <code>\ingroup</code>, <code>\brief</code>) is on the top of every file, so the documentation of the module is generated from the same folder,</li>
<li class="">the includes are ordered <code>&lt;system&gt;</code>, then the project, then the module.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-name-in-all-places">One name in all places<a href="https://embedbits.cz/blog/file-organization-embedded-c#one-name-in-all-places" class="hash-link" aria-label="Direct link to One name in all places" title="Direct link to One name in all places" translate="no">​</a></h2>
<p>The strength of this organization is that the name of the module is the same everywhere, so you can guess a name without looking it up:</p>





































<table><thead><tr><th>What</th><th>Example</th></tr></thead><tbody><tr><td>Folder</td><td><code>Temperature/</code></td></tr><tr><td>Library in CMake</td><td><code>Temperature_Lib</code></td></tr><tr><td>Files</td><td><code>Temperature.c</code>, <code>Temperature_Port.h</code>, <code>Temperature_Types.h</code></td></tr><tr><td>Functions</td><td><code>Temperature_Init()</code>, <code>Temperature_Get_Value()</code></td></tr><tr><td>Types</td><td><code>temperature_Value_t</code>, <code>temperature_RequestState_t</code></td></tr><tr><td>Macros and enumerators</td><td><code>TEMPERATURE_REQUEST_OK</code></td></tr><tr><td>Include guard</td><td><code>TEMPERATURE_TEMPERATURE_PORT_H</code></td></tr></tbody></table>
<p>If you see <code>Gpio_Set_PinLevel()</code> in a stack trace, you know that it is in the folder <code>Gpio</code>, in the library <code>Gpio_Lib</code> and that its types start with <code>gpio_</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-same-lifecycle-for-every-module">The same lifecycle for every module<a href="https://embedbits.cz/blog/file-organization-embedded-c#the-same-lifecycle-for-every-module" class="hash-link" aria-label="Direct link to The same lifecycle for every module" title="Direct link to The same lifecycle for every module" translate="no">​</a></h3>
<p>The generated module comes with the four functions that every module has: <code>Get_ModuleVersion()</code>, <code>Init()</code>, <code>Deinit()</code> and <code>Task()</code>. <code>Init</code> sets up the module and handles its own failures, <code>Task</code> is called periodically from the main loop or from a scheduler. The consequence is that the code on top (<code>AppMain</code>) can treat all modules in the same way, and a new module does not need a new concept.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="creating-a-module">Creating a module<a href="https://embedbits.cz/blog/file-organization-embedded-c#creating-a-module" class="hash-link" aria-label="Direct link to Creating a module" title="Direct link to Creating a module" translate="no">​</a></h2>
<p>You do not create these files by hand. The project tools of the platform (the <em>Create module</em> entry of the menu, described on the page <a class="" href="https://embedbits.cz/docs/platform/embi-platform/cmake-helpertools">Project tools</a>) ask for the name and the location, and generate the folder with all the files above and the <code>CMakeLists.txt</code>. The <em>Add component</em> entry adds a <code>Module_Component.c/.h</code> pair to an existing module. A module that was generated once is never overwritten, so it is safe to run the tool again.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-rules-in-a-short-form">The rules in a short form<a href="https://embedbits.cz/blog/file-organization-embedded-c#the-rules-in-a-short-form" class="hash-link" aria-label="Direct link to The rules in a short form" title="Direct link to The rules in a short form" translate="no">​</a></h2>
<ol>
<li class="">One module is one folder, and it has its own library.</li>
<li class="">Other modules include <strong>only</strong> <code>Module_Port.h</code> and <code>Module_Types.h</code>.</li>
<li class="">Internal headers are not in the list of public headers.</li>
<li class="">The data is <code>static</code> in the <code>.c</code> file, access goes through functions. No <code>extern</code> variables.</li>
<li class="">The file name begins with the module name, and so does every function, type and macro.</li>
<li class="">Vendor code is never edited. Your changes live in the handler folder next to it.</li>
<li class="">The calls go down in the layers, never up.</li>
<li class="">Everything in a file is in its section, in the same order.</li>
</ol>
<p>None of these rules is clever. The point is that all of them are the same in all modules, so after you have read one module, you know how to read all the others. That is also the reason why the platform generates the files: a convention that takes work to follow is a convention that is not followed.</p>
<p>The same ideas, from a different point of view, are in the articles about <a class="" href="https://embedbits.cz/blog/solid-principles-c-cpp">SOLID principles</a> (the port header is the interface that other modules depend on) and about <a class="" href="https://embedbits.cz/blog/misra-c-rules-in-practice">MISRA C</a> (several of the rules are much easier to follow when the code is organized like this).</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="Architecture" term="Architecture"/>
        <category label="C" term="C"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[MISRA C rules in practice: what they are, why they exist and how to live with them]]></title>
        <id>https://embedbits.cz/blog/misra-c-rules-in-practice</id>
        <link href="https://embedbits.cz/blog/misra-c-rules-in-practice"/>
        <updated>2026-10-04T10:00:00.000Z</updated>
        <summary type="html"><![CDATA[Say "MISRA" in a room full of embedded developers and half of them will sigh, and the other half will ask which tool you use. The reputation of the rules is mixed: for some they are the bureaucracy that eats a week before every release, for others the reason why a car does not reboot on the highway. Both groups are partly right.]]></summary>
        <content type="html"><![CDATA[<p>Say "MISRA" in a room full of embedded developers and half of them will sigh, and the other half will ask which tool you use. The reputation of the rules is mixed: for some they are the bureaucracy that eats a week before every release, for others the reason why a car does not reboot on the highway. Both groups are partly right.</p>
<p>In this article I will go through the rules that I meet most often, one by one: what the rule asks for, what you get for it, what the bad code looks like, what the good code looks like and who finds the problem for you. All examples are real C code that I compiled and ran.</p>
<!-- -->
<blockquote>
<p><strong>A word about the rule texts</strong></p>
<p>MISRA C is a copyrighted document of the MISRA consortium. I do not copy its wording here. Every rule is described in my own words, with my own examples, and only the numbers and the categories are quoted. The numbers refer to <strong>MISRA C:2012</strong> (MISRA C:2023 consolidates the amendments, keeps these numbers and adds a few new guidelines). Before you build anything on this article, check the rule in your own copy of the standard, which you can get at <a href="https://misra.org.uk/" target="_blank" rel="noopener noreferrer" class="">misra.org.uk</a>. This article is independent and not endorsed by MISRA.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-misra-c-is-and-what-it-is-not">What MISRA C is (and what it is not)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#what-misra-c-is-and-what-it-is-not" class="hash-link" aria-label="Direct link to What MISRA C is (and what it is not)" title="Direct link to What MISRA C is (and what it is not)" translate="no">​</a></h2>
<p>MISRA stands for <em>Motor Industry Software Reliability Association</em>. The first guidelines for C were published in 1998 for the automotive industry, today they are used in aerospace, rail, medical devices and industrial automation, basically everywhere where a software failure hurts somebody.</p>
<p>The central idea is simple. C is a language that allows a lot of things that are legal but dangerous: undefined behaviour, implementation defined behaviour, implicit conversions that change values, pointers that can point anywhere. MISRA defines a <strong>subset of C</strong> in which the dangerous parts are forbidden or have to be justified. It is not a different language, and a MISRA compliant program is still a normal C program that your normal compiler builds.</p>
<p>What MISRA is <strong>not</strong>:</p>
<ul>
<li class="">It is not a certification. "MISRA compliant" is a claim that you make and document, nobody stamps your code.</li>
<li class="">It is not a guarantee of correctness. The rules remove classes of bugs, they do not check that the thermostat controls the temperature.</li>
<li class="">It is not about style. Naming, indentation and file organization are not part of MISRA, that is what a <a class="" href="https://embedbits.cz/docs/platform/embi-platform/coding-style">coding style</a> is for.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-read-a-rule">How to read a rule<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#how-to-read-a-rule" class="hash-link" aria-label="Direct link to How to read a rule" title="Direct link to How to read a rule" translate="no">​</a></h3>
<p>Each guideline has three properties which you should know before you read the first one:</p>

























<table><thead><tr><th>Property</th><th>Values</th><th>Meaning</th></tr></thead><tbody><tr><td><strong>Kind</strong></td><td><em>Directive</em> / <em>Rule</em></td><td>A rule can be checked by looking at the source code alone. A directive needs more information (a design, a process), so a tool can help but cannot decide.</td></tr><tr><td><strong>Category</strong></td><td><em>Mandatory</em> / <em>Required</em> / <em>Advisory</em></td><td>Mandatory: no deviation. Required: a deviation is possible with a written justification. Advisory: recommendation, you only have to record that you do not follow it.</td></tr><tr><td><strong>Decidability</strong></td><td><em>Decidable</em> / <em>Undecidable</em></td><td>Whether a tool can give an exact answer. For undecidable rules even the best analyzer produces false positives or misses something.</td></tr></tbody></table>
<p>The numbering is <code>Dir 4.12</code> for directives and <code>Rule 9.1</code> for rules, where the first number is the topic (9 = initialization, 10 = types, 11 = pointers, ...).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-rules-one-by-one">The rules, one by one<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#the-rules-one-by-one" class="hash-link" aria-label="Direct link to The rules, one by one" title="Direct link to The rules, one by one" translate="no">​</a></h2>
<p>I grouped them by the problem they solve, not by the number.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-about-values-that-are-not-what-you-think">Rules about values that are not what you think<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-about-values-that-are-not-what-you-think" class="hash-link" aria-label="Direct link to Rules about values that are not what you think" title="Direct link to Rules about values that are not what you think" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-91---read-before-write-mandatory">Rule 9.1 - read before write (Mandatory)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-91---read-before-write-mandatory" class="hash-link" aria-label="Direct link to Rule 9.1 - read before write (Mandatory)" title="Direct link to Rule 9.1 - read before write (Mandatory)" translate="no">​</a></h4>
<p><strong>The rule:</strong> do not read a variable with automatic storage before a value was assigned to it.</p>
<p><strong>What you get:</strong> the value of such a variable is garbage, and on a different compiler or optimization level it is <em>different</em> garbage. Bugs like "works in debug, fails in release" very often end here. Because the rule is mandatory, no deviation is possible.</p>
<p>Bad, the variable is set only on one path:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gain_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool isHigh</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> gain</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">isHigh</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> gain </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> gain</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* indeterminate value when isHigh is false */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Good, every path has a defined value:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Gain_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool isHigh</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> gain </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">isHigh</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> gain </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> gain</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><strong>Who finds it:</strong> the compiler sometimes (<code>-Wall -Wmaybe-uninitialized</code> with optimization), a static analyzer reliably. In my test build, gcc stayed silent on this function. Do not rely on it.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-101-103-104---essential-types-required">Rules 10.1, 10.3, 10.4 - essential types (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-101-103-104---essential-types-required" class="hash-link" aria-label="Direct link to Rules 10.1, 10.3, 10.4 - essential types (Required)" title="Direct link to Rules 10.1, 10.3, 10.4 - essential types (Required)" translate="no">​</a></h4>
<p><strong>The rules:</strong> the MISRA authors invented the <em>essential type model</em>: the type that an expression <em>looks like</em> it has (an <code>uint8_t</code> stays "unsigned 8 bit" in their view), in contrast to the type that C silently uses (<code>int</code>, because of the integer promotion). The rules forbid operations between inappropriate types, assigning a value to a narrower type and mixing categories (signed, unsigned, boolean, character, floating).</p>
<p><strong>What you get:</strong> the integer promotions are the largest source of surprises in embedded C. All values smaller than <code>int</code> are promoted to <code>int</code> before any arithmetic, and you do not see it. Two classic results:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Flags_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> flags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token plain">flags </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0xF0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ~flags is an int: 0xFFFFFFF0 - never equal */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><code>~flags</code> is not an 8 bit value, it is an <code>int</code> with the value <code>0xFFFFFFF0</code>. The comparison never succeeds, whatever the argument is. The fix is to say what you mean:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Flags_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> flags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token plain">flags </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0xF0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The second classic is the silent narrowing:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Add_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">      </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* int result silently narrowed */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><code>200 + 100</code> is calculated as <code>int</code> (300), and the assignment to <code>uint8_t</code> keeps only 44. No warning, no error, a wrong sum. Two correct variants: widen the result, or cast deliberately and think about the overflow.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Add_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">first </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><strong>Who finds it:</strong> a good static analyzer. The compiler helps only partly: <code>-Wsign-compare</code> (part of <code>-Wextra</code>) reported the first example, while gcc stayed silent on the second one.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="directive-46---types-with-size-and-signedness-advisory">Directive 4.6 - types with size and signedness (Advisory)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#directive-46---types-with-size-and-signedness-advisory" class="hash-link" aria-label="Direct link to Directive 4.6 - types with size and signedness (Advisory)" title="Direct link to Directive 4.6 - types with size and signedness (Advisory)" translate="no">​</a></h4>
<p><strong>The directive:</strong> use typedefs that tell the size and the signedness (<code>uint8_t</code>, <code>int32_t</code>, or your own names) instead of <code>char</code>, <code>short</code>, <code>int</code> and <code>long</code>.</p>
<p><strong>What you get:</strong> the width of <code>int</code> depends on the compiler and the MCU: 16 bit on small 8 and 16 bit controllers, 32 bit on a Cortex-M. A code that works on one target silently changes on another. With fixed width types it is visible in the source what the code does. In my projects I go one step further and make own type names for physical values (<code>temperature_t</code>, <code>humidity_t</code>), so the compiler stops me when I mix them.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> counter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 16 or 32 bits? the answer depends on the target */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token plain"> counter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 16 bits everywhere */</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-13---no-undefined-behaviour-required">Rule 1.3 - no undefined behaviour (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-13---no-undefined-behaviour-required" class="hash-link" aria-label="Direct link to Rule 1.3 - no undefined behaviour (Required)" title="Direct link to Rule 1.3 - no undefined behaviour (Required)" translate="no">​</a></h4>
<p><strong>The rule:</strong> the program must not contain undefined behaviour. This includes the signed overflow, shifts by too many bits, a division by zero, use of a dangling pointer and many more.</p>
<p><strong>What you get:</strong> with undefined behaviour the compiler may do <em>anything</em>, including the removal of your safety check, because "this case cannot happen". The most known example is the signed overflow: <code>first + second</code> on <code>int32_t</code> that does not fit is not "wrap around", it is a license for the optimizer.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">int32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Add_Bad2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">int32_t</span><span class="token plain"> first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">int32_t</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">             </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* signed overflow is undefined behaviour */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The correct code checks the condition <em>before</em> the operation and reports the problem to the caller:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Add_Safe</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">int32_t</span><span class="token plain"> first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">int32_t</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">int32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    bool isOk </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">second </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">first </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">INT32_MAX </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">||</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">second </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">first </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">INT32_MIN </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        isOk </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">result </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> isOk</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The same applies to shifts. The mask of a bit position is only defined if the position is smaller than the width of the type:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Bit_Mask</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> position</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">position </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">32u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token plain"> position</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><strong>Who finds it:</strong> partly the compiler (<code>-fsanitize=undefined</code> finds it at run time during tests), partly the analyzer. The rule is undecidable in general: a tool can show you all the places which could be a problem.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-about-conditions-and-control-flow">Rules about conditions and control flow<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-about-conditions-and-control-flow" class="hash-link" aria-label="Direct link to Rules about conditions and control flow" title="Direct link to Rules about conditions and control flow" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-144---controlling-expression-is-a-boolean-required">Rule 14.4 - controlling expression is a boolean (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-144---controlling-expression-is-a-boolean-required" class="hash-link" aria-label="Direct link to Rule 14.4 - controlling expression is a boolean (Required)" title="Direct link to Rule 14.4 - controlling expression is a boolean (Required)" translate="no">​</a></h4>
<p><strong>The rule:</strong> the condition of <code>if</code>, <code>while</code> and <code>for</code> has to be an expression that has the essential Boolean type, i.e. the result of a comparison or a <code>bool</code>. An integer or a pointer alone is not allowed.</p>
<p><strong>What you get:</strong> the intention is readable. <code>while (count)</code> does not tell whether you want "while it is not zero" or "while it is not the end". The explicit form looks the same for numbers, pointers and flags. (I write the constant on the left side, <code>0u != count</code>, so a typo with a single <code>=</code> does not compile.)</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Count_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> count</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> steps </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">count</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> count</span><span class="token operator" style="color:rgb(137, 221, 255)">--</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> steps</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Count_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> count</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> steps </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> count</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> count</span><span class="token operator" style="color:rgb(137, 221, 255)">--</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> steps</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><strong>Who finds it:</strong> every MISRA analyzer, it is a decidable rule.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-121---make-the-operator-precedence-explicit-advisory">Rule 12.1 - make the operator precedence explicit (Advisory)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-121---make-the-operator-precedence-explicit-advisory" class="hash-link" aria-label="Direct link to Rule 12.1 - make the operator precedence explicit (Advisory)" title="Direct link to Rule 12.1 - make the operator precedence explicit (Advisory)" translate="no">​</a></h4>
<p><strong>The rule:</strong> do not rely on the reader (and yourself) to remember the precedence table, use parentheses.</p>
<p><strong>What you get:</strong> the precedence of <code>&amp;</code> and <code>==</code> in C is the opposite of what the human brain expects. This is the bug that everyone writes at least once:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Masked_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> flags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">flags </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> MASK </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> MASK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* == binds stronger than &amp; */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><code>MASK == MASK</code> is evaluated first and gives <code>1</code>, so the function tests the bit 0 and not the mask. It returns <code>true</code> for <code>0x01</code> and <code>false</code> for <code>0x0C</code>, exactly wrong. With the parentheses the bug cannot exist:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Masked_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> flags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">flags </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> MASK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> MASK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><strong>Who finds it:</strong> the compiler (<code>-Wparentheses</code> is part of <code>-Wall</code>) and every analyzer.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-156-157-163-and-164---complete-statements-required">Rules 15.6, 15.7, 16.3 and 16.4 - complete statements (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-156-157-163-and-164---complete-statements-required" class="hash-link" aria-label="Direct link to Rules 15.6, 15.7, 16.3 and 16.4 - complete statements (Required)" title="Direct link to Rules 15.6, 15.7, 16.3 and 16.4 - complete statements (Required)" translate="no">​</a></h4>
<p><strong>The rules:</strong></p>
<ul>
<li class="">15.6: the body of <code>if</code>, <code>else</code>, <code>for</code>, <code>while</code> is always a block in braces,</li>
<li class="">15.7: every <code>if ... else if</code> chain ends with an <code>else</code>,</li>
<li class="">16.3: every <code>switch</code> clause ends with <code>break</code> (or another unconditional jump),</li>
<li class="">16.4: every <code>switch</code> has a <code>default</code>.</li>
</ul>
<p><strong>What you get:</strong> the rules force you to answer the question "what happens in all the other cases?" at the moment when you write the code and not in the field. A <code>switch</code> without a <code>break</code> is a classic bug, an <code>enum</code> that gets a new value without a <code>default</code> is the second one. The braces remove the family of bugs where a second statement is added under an <code>if</code> and looks like it is conditional:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">isError</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Led_On</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Buzzer_On</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">      </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* indented like it belongs to the if - it does not */</span><br></div></code></pre></div></div>
<p>And here is the switch. The first version falls from <code>MODE_ON</code> into <code>MODE_ERROR</code> and sets the wrong value, the second one handles every case explicitly:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Mode_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">mode_t_ mode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> MODE_ON</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            gLeds </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> MODE_ERROR</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain">               </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* falls through by accident */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            gLeds </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">break</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Mode_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">mode_t_ mode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> MODE_ON</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            gLeds </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">break</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> MODE_ERROR</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            gLeds </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">break</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> MODE_OFF</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">default</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            gLeds </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">break</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>In my test gcc found the missing <code>default</code> and the fall-through (<code>-Wswitch-default -Wimplicit-fallthrough</code>). The <code>else</code> rule and the braces are checked by an analyzer or by the formatter.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-172---no-recursion-required">Rule 17.2 - no recursion (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-172---no-recursion-required" class="hash-link" aria-label="Direct link to Rule 17.2 - no recursion (Required)" title="Direct link to Rule 17.2 - no recursion (Required)" translate="no">​</a></h4>
<p><strong>The rule:</strong> a function must not call itself, neither directly nor through other functions.</p>
<p><strong>What you get:</strong> on a PC the stack has megabytes. On a microcontroller you have a few kilobytes, and the worst case of the recursion depth depends on the input data. If you remove recursion, the maximal stack usage can be <em>calculated</em> (the static analysis of the call tree is enough), and a stack overflow stops being a surprise.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Factorial_Recursive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> value </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Factorial_Recursive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The iterative version needs a constant amount of the stack:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Factorial_Iterative</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> factor </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> factor </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> factor</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(137, 221, 255)">*=</span><span class="token plain"> factor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><strong>Who finds it:</strong> the analyzer and the linker map (some toolchains print the call graph, <code>-fstack-usage</code> tells the size of each frame).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-about-memory-and-pointers">Rules about memory and pointers<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-about-memory-and-pointers" class="hash-link" aria-label="Direct link to Rules about memory and pointers" title="Direct link to Rules about memory and pointers" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="directive-412-and-rule-213---no-dynamic-memory-required">Directive 4.12 and Rule 21.3 - no dynamic memory (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#directive-412-and-rule-213---no-dynamic-memory-required" class="hash-link" aria-label="Direct link to Directive 4.12 and Rule 21.3 - no dynamic memory (Required)" title="Direct link to Directive 4.12 and Rule 21.3 - no dynamic memory (Required)" translate="no">​</a></h4>
<p><strong>The rule:</strong> do not use <code>malloc</code>, <code>calloc</code>, <code>realloc</code> and <code>free</code>.</p>
<p><strong>What you get:</strong></p>
<ul>
<li class="">the heap <em>fragments</em>. After weeks of running a request for 64 bytes can fail although 10 kB are free, only not in one piece,</li>
<li class="">the execution time of <code>malloc</code> is not deterministic,</li>
<li class="">a memory leak after weeks of running is the worst kind of the bug to find,</li>
<li class="">the memory consumption is known at link time, not at 3 a.m. in the field.</li>
</ul>
<p>A standard alternative is a pool with a fixed size, which has the same API shape as the allocator:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">FRAME_POOL_SIZE</span><span class="token macro property"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">4u</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    bool    inUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">frame_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">frame_t</span><span class="token plain"> framePool</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">FRAME_POOL_SIZE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">frame_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token function" style="color:rgb(130, 170, 255)">Frame_Acquire</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> FRAME_POOL_SIZE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token plain">framePool</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">inUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> framePool</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">inUse </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">framePool</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* the caller has to handle "no frame" - at test time, not at 3 a.m. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The function returns <code>NULL</code> if all frames are taken, so the case "no memory" is handled in the code and is testable on a PC. Exactly the same happens with <code>malloc</code>, only you cannot test it, because on your PC the allocation never fails.</p>
<p><strong>Who finds it:</strong> the analyzer, or simply a linker which does not link <code>malloc</code> at all.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-113-and-115---careful-with-pointer-casts-required--advisory">Rules 11.3 and 11.5 - careful with pointer casts (Required / Advisory)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-113-and-115---careful-with-pointer-casts-required--advisory" class="hash-link" aria-label="Direct link to Rules 11.3 and 11.5 - careful with pointer casts (Required / Advisory)" title="Direct link to Rules 11.3 and 11.5 - careful with pointer casts (Required / Advisory)" translate="no">​</a></h4>
<p><strong>The rules:</strong> do not cast a pointer to an object of one type to a pointer to an object of another type (11.3), and avoid the conversion from <code>void *</code> to an object pointer (11.5).</p>
<p><strong>What you get:</strong> the cast of a byte buffer to <code>uint32_t *</code> is the most common way to read a field of a communication frame:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ReadU32_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* misaligned access, strict aliasing violation */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>It is undefined behaviour twice. The address does not need to be aligned to four bytes (a hard fault on a Cortex-M0, a slow access somewhere else), and the access through a pointer of another type violates the aliasing rules, so the optimizer may reorder or drop it. Two correct solutions: <code>memcpy</code> (the compiler turns it into a single load where the hardware allows it) or an assembly of the bytes, which also fixes the byte order and does not depend on the endianness of the CPU:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ReadU32_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token function" style="color:rgb(130, 170, 255)">memcpy</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">sizeof</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ReadU32LittleEndian</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">16</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">24</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The cast of <code>void *</code> is typical for a generic callback context. It is advisory because in C it is sometimes the only way. The benefit of the rule is that you will notice every such place and do the cast at a single line in the beginning of the function (as in the <a class="" href="https://embedbits.cz/blog/solid-principles-c-cpp">article about SOLID</a>), and not everywhere.</p>
<p><strong>Who finds it:</strong> every analyzer. A compiler finds the cast only on some targets and with <code>-Wcast-align</code>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-813---a-pointer-to-const-when-possible-advisory">Rule 8.13 - a pointer to const when possible (Advisory)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-813---a-pointer-to-const-when-possible-advisory" class="hash-link" aria-label="Direct link to Rule 8.13 - a pointer to const when possible (Advisory)" title="Direct link to Rule 8.13 - a pointer to const when possible (Advisory)" translate="no">​</a></h4>
<p><strong>The rule:</strong> if a function does not change the data behind a pointer, the pointer is declared as a pointer to <code>const</code>.</p>
<p><strong>What you get:</strong> the signature is a contract. The caller sees from the prototype that the function only reads, and the compiler guards it. A <code>const</code> buffer from the flash can be passed only to a function with <code>const</code>, otherwise the code does not compile (or worse, it writes to the flash and causes a fault).</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Checksum_Bad</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sum </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Checksum_Good</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> index</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sum </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-about-the-code-you-wrote-and-the-code-that-is-not-there">Rules about the code you wrote and the code that is not there<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-about-the-code-you-wrote-and-the-code-that-is-not-there" class="hash-link" aria-label="Direct link to Rules about the code you wrote and the code that is not there" title="Direct link to Rules about the code you wrote and the code that is not there" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-177-and-directive-47---do-not-ignore-results-required">Rule 17.7 and Directive 4.7 - do not ignore results (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-177-and-directive-47---do-not-ignore-results-required" class="hash-link" aria-label="Direct link to Rule 17.7 and Directive 4.7 - do not ignore results (Required)" title="Direct link to Rule 17.7 and Directive 4.7 - do not ignore results (Required)" translate="no">​</a></h4>
<p><strong>The rules:</strong> a returned value must be used (17.7), and when a function returns an error code, it has to be tested (4.7).</p>
<p><strong>What you get:</strong> an ignored return value is an ignored error. The sending of a frame to a busy UART, a refused write to the flash, a timeout of the I2C: all of them silently pass, and the application continues with a wrong assumption. If you really do not care, say it with <code>(void)</code>, so the reader (and the analyzer) knows that it was a decision and not a mistake:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Send_Checked</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">UART_OK </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">sizeof</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* a log message, loss is acceptable */</span><br></div></code></pre></div></div>
<p><strong>Who finds it:</strong> the analyzer, in gcc with <code>__attribute__((warn_unused_result))</code> on your own API.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-21-and-22---no-unreachable-and-no-dead-code-required">Rules 2.1 and 2.2 - no unreachable and no dead code (Required)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rules-21-and-22---no-unreachable-and-no-dead-code-required" class="hash-link" aria-label="Direct link to Rules 2.1 and 2.2 - no unreachable and no dead code (Required)" title="Direct link to Rules 2.1 and 2.2 - no unreachable and no dead code (Required)" translate="no">​</a></h4>
<p><strong>The rules:</strong> the project must not contain code that can never be executed (2.1), and code which is executed but has no influence on the result (2.2).</p>
<p><strong>What you get:</strong> both kinds are a signal of a mistake: a condition which never occurs, a forgotten <code>return</code>, or a copy-paste error. Dead code also falsifies the test coverage (you cannot reach 100 % of the lines which no input executes) and it makes the reader to think about it. Both appear in this function:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Level_Get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> raw</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> level </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* dead: overwritten before it is read */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    level </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">raw </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> level</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Level_Log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">raw</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* unreachable */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The first assignment of <code>level</code> is dead and the last line is unreachable.</p>
<p><strong>Who finds it:</strong> the analyzer. gcc with <code>-Wall -Wextra</code> was silent in my test.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-207-and-directive-49---macros-with-parameters-required--advisory">Rule 20.7 and Directive 4.9 - macros with parameters (Required / Advisory)<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#rule-207-and-directive-49---macros-with-parameters-required--advisory" class="hash-link" aria-label="Direct link to Rule 20.7 and Directive 4.9 - macros with parameters (Required / Advisory)" title="Direct link to Rule 20.7 and Directive 4.9 - macros with parameters (Required / Advisory)" translate="no">​</a></h4>
<p><strong>The rule:</strong> an expanded macro parameter has to be in parentheses (20.7), and a function is preferred to a function-like macro (4.9).</p>
<p><strong>What you get:</strong> a macro is a text replacement. If you do not protect the parameter, the precedence of the <em>caller</em> decides:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name function" style="color:rgb(130, 170, 255)">SQUARE_BAD</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">x</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression">  x </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression"> x</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name function" style="color:rgb(130, 170, 255)">SQUARE_OK</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">x</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression">   </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">x</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression">x</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">SQUARE_BAD</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* 2 + 1 * 2 + 1 = 5, not 9 */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">SQUARE_OK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ((2 + 1) * (2 + 1)) = 9 */</span><br></div></code></pre></div></div>
<p>Even the protected macro has a problem: <code>SQUARE_OK(count++)</code> increments twice. That is why directive 4.9 recommends a function. An inline function has a type, evaluates the argument once and costs the same:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Square</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> value </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-misra-in-a-real-project">Using MISRA in a real project<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#using-misra-in-a-real-project" class="hash-link" aria-label="Direct link to Using MISRA in a real project" title="Direct link to Using MISRA in a real project" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="compiler-warnings-are-the-first-step-not-the-last">Compiler warnings are the first step, not the last<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#compiler-warnings-are-the-first-step-not-the-last" class="hash-link" aria-label="Direct link to Compiler warnings are the first step, not the last" title="Direct link to Compiler warnings are the first step, not the last" translate="no">​</a></h3>
<p>I compiled all the examples above with <code>gcc -Wall -Wextra -Wconversion -Wshadow -Wswitch-default -Wimplicit-fallthrough -O2</code>. gcc reported five warnings, and they belong to only three of the "bad" examples: the comparison with the promoted complement, the <code>switch</code> (missing <code>default</code>, unhandled enum value and the fall-through) and the missing parentheses around <code>==</code> in a mask test. It stayed silent about the narrowing, the uninitialized variable, the dead and the unreachable code, the signed overflow, the recursion, the pointer cast and the macro.</p>
<p>My recommendation is a compiler with the maximum of warnings and <code>-Werror</code> in the CI as the baseline. It is free and it removes the most obvious problems, but it is not a replacement of the static analysis.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="choose-a-tool-and-put-it-in-the-ci">Choose a tool and put it in the CI<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#choose-a-tool-and-put-it-in-the-ci" class="hash-link" aria-label="Direct link to Choose a tool and put it in the CI" title="Direct link to Choose a tool and put it in the CI" translate="no">​</a></h3>
<p>To check the rules you need a static analyzer. There are commercial ones (Polyspace, Helix QAC, PC-lint Plus, Coverity, Parasoft C/C++test, LDRA, IAR C-STAT and others) and free ones which cover a part of the rules, for example <a href="https://cppcheck.sourceforge.io/" target="_blank" rel="noopener noreferrer" class="">cppcheck</a> with its MISRA addon. The addon needs the text of the rules as an input, and because of the copyright you have to provide it from your own copy of the standard. A tool is never perfect: for undecidable rules you will have false positives, and sometimes a violation is missed.</p>
<p>The check belongs into the CI of every commit, not into a manual run before the release. Otherwise you do the same work three times: once when you write, once when the violations are found and once when you fix them.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="deviations-are-part-of-the-system">Deviations are part of the system<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#deviations-are-part-of-the-system" class="hash-link" aria-label="Direct link to Deviations are part of the system" title="Direct link to Deviations are part of the system" translate="no">​</a></h3>
<p>Sometimes a rule must be broken. A hardware register access needs a cast of an integer to a pointer, a bootloader needs to write to the flash through a pointer. MISRA knows it and defines a <strong>deviation</strong>: a record with the rule, the place, the reason and the risk assessment. The record should be next to the code:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* MISRA deviation: Rule 11.4 (Advisory), see DEV-012</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Reason: the address of the peripheral register is fixed by the hardware.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Contained in this macro, the rest of the code uses the register type. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">UART_REGS</span><span class="token macro property"> </span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token macro property expression class-name" style="color:rgb(255, 203, 107)">uartRegisters_t</span><span class="token macro property expression"> </span><span class="token macro property expression operator" style="color:rgb(137, 221, 255)">*</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">0x40004400u</span><span class="token macro property expression punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>A deviation is not a failure. A list of well argued deviations is the sign of a project in which people think. A project with zero deviations and without hardware access is usually either lying or very small.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="legacy-code-and-vendor-code">Legacy code and vendor code<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#legacy-code-and-vendor-code" class="hash-link" aria-label="Direct link to Legacy code and vendor code" title="Direct link to Legacy code and vendor code" translate="no">​</a></h3>
<p>You will not make the 200 000 lines of an old project compliant in a week. What works:</p>
<ol>
<li class=""><strong>Do not touch the old code,</strong> enable the check for <em>new and changed</em> files. The analyzer's baseline stores the existing violations, and the CI fails only on new ones.</li>
<li class=""><strong>Start with the mandatory and required rules,</strong> advisory ones later.</li>
<li class=""><strong>Exclude third-party code</strong> and document it. The generated code of the vendor (HAL, LL, CMSIS) is not yours to fix. This is one more reason for the layered architecture from the article about <a class="" href="https://embedbits.cz/blog/design-architecture">design and architecture</a>: when the vendor code sits in the RAL, and the MCAL and everything above it is your code, the borderline of the check is a folder.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-does-not-help">What does not help<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#what-does-not-help" class="hash-link" aria-label="Direct link to What does not help" title="Direct link to What does not help" translate="no">​</a></h3>
<ul>
<li class=""><strong>Chasing the number of violations.</strong> A rule fixed in a way that satisfies the tool and breaks the sense (a cast added only to silence the warning) is worse than the original.</li>
<li class=""><strong>Using MISRA as an argument.</strong> "MISRA says so" is not a reason. If you cannot explain what the rule protects you from, you will not be able to decide when it is time for a deviation.</li>
<li class=""><strong>Believing that compliance means correct.</strong> MISRA makes some mistakes impossible. The requirements, the architecture, the review and the tests stay yours.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://embedbits.cz/blog/misra-c-rules-in-practice#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
















































































<table><thead><tr><th>Rule</th><th>In short</th><th>Benefit</th></tr></thead><tbody><tr><td>9.1</td><td>Initialize before reading</td><td>No random values, same behavior in debug and release</td></tr><tr><td>10.x</td><td>Respect the essential types</td><td>No surprises from integer promotion and narrowing</td></tr><tr><td>Dir 4.6</td><td>Fixed width types</td><td>The same code means the same on every target</td></tr><tr><td>1.3</td><td>No undefined behavior</td><td>The optimizer cannot remove your checks</td></tr><tr><td>14.4</td><td>Explicit conditions</td><td>The intention is readable</td></tr><tr><td>12.1</td><td>Parentheses</td><td>No precedence bugs</td></tr><tr><td>15.6, 15.7, 16.3, 16.4</td><td>Braces, <code>else</code>, <code>break</code>, <code>default</code></td><td>Every case is handled</td></tr><tr><td>17.2</td><td>No recursion</td><td>Stack usage can be calculated</td></tr><tr><td>Dir 4.12, 21.3</td><td>No dynamic memory</td><td>No fragmentation, leaks and surprises in timing</td></tr><tr><td>11.3, 11.5</td><td>No pointer type tricks</td><td>No alignment and aliasing bugs</td></tr><tr><td>8.13</td><td><code>const</code> pointers</td><td>The signature is a contract</td></tr><tr><td>17.7, Dir 4.7</td><td>Use the return values</td><td>Errors do not disappear</td></tr><tr><td>2.1, 2.2</td><td>No unreachable or dead code</td><td>Mistakes are visible, coverage is meaningful</td></tr><tr><td>20.7, Dir 4.9</td><td>Safe macros, prefer functions</td><td>No hidden double evaluation or precedence bugs</td></tr></tbody></table>
<p>If you remember one thing: <strong>a MISRA rule is the scar of a bug that somebody already had.</strong> You do not need to like the rules, but it is good to know what each of them is a scar of. Then you will know when to follow it, and when to write a deviation and take the responsibility.</p>
<p>The rules described here are only a selection. The full set has more than 140 guidelines, and the rest (the preprocessor, the standard library, the structure of the declarations) is worth reading in your copy of the standard, once.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="C" term="C"/>
        <category label="MISRA" term="MISRA"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[SOLID principles: from C++ classes to plain C]]></title>
        <id>https://embedbits.cz/blog/solid-principles-c-cpp</id>
        <link href="https://embedbits.cz/blog/solid-principles-c-cpp"/>
        <updated>2026-10-03T21:00:00.000Z</updated>
        <summary type="html"><![CDATA[Five letters that every job interview in software engineering seems to contain. S, O, L, I and D. The principles were described for object oriented languages, so the common conclusion is "SOLID is for C++ and Java, we write C, so we are done". That conclusion is wrong, and I will try to show why. For every principle you will find the original idea with a C++ example, and then the same idea in C, without classes, without inheritance and without a single virtual.]]></summary>
        <content type="html"><![CDATA[<p>Five letters that every job interview in software engineering seems to contain. S, O, L, I and D. The principles were described for object oriented languages, so the common conclusion is "SOLID is for C++ and Java, we write C, so we are done". That conclusion is wrong, and I will try to show why. For every principle you will find the original idea with a C++ example, and then the same idea in C, without classes, without inheritance and without a single <code>virtual</code>.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-solid-comes-from">Where SOLID comes from<a href="https://embedbits.cz/blog/solid-principles-c-cpp#where-solid-comes-from" class="hash-link" aria-label="Direct link to Where SOLID comes from" title="Direct link to Where SOLID comes from" translate="no">​</a></h2>
<p>The principles were collected by Robert C. Martin ("Uncle Bob") in the early 2000s, the acronym itself was coined by Michael Feathers. Some of the ideas are much older: the <em>open/closed principle</em> comes from Bertrand Meyer (1988) and the <em>Liskov substitution principle</em> from Barbara Liskov (1987).</p>
<p>All of them answer one question: <strong>how do I write code that survives change?</strong> Not code that works today, but code that can be extended, tested and maintained by the guy from the quote on the front page, who knows where you live.</p>
<p>The C++ examples use classes and virtual functions because that is how the principles were originally explained. The C examples follow <a class="" href="https://embedbits.cz/docs/platform/embi-platform/coding-style">my coding style</a>: <code>Module_Function</code> names, <code>_t</code> types and variables with meaningful names. One exception for the sake of the length: I use the plain <code>uint8_t</code>, <code>uint32_t</code> and <code>float</code> where a real project would use its own typedefs (<code>temperature_t</code>, <code>voltage_t</code>), which the coding style requires. All examples in this article were compiled (<code>gcc -std=c11 -Wall -Wextra -pedantic</code> and <code>g++ -std=c++17</code>) and run with a small unit test, including the "bad" ones.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-a-class-really-is">What a class really is<a href="https://embedbits.cz/blog/solid-principles-c-cpp#what-a-class-really-is" class="hash-link" aria-label="Direct link to What a class really is" title="Direct link to What a class really is" translate="no">​</a></h3>
<p>Before we start, a short reminder of what the compiler does behind the scenes. A C++ class with virtual functions is:</p>
<ul>
<li class="">a <code>struct</code> with the data of the object,</li>
<li class="">a hidden pointer in this struct to a table of function pointers (the <em>vtable</em>), one table per class,</li>
<li class="">a convention that every method gets the pointer to the object as the first parameter (<code>this</code>).</li>
</ul>
<p>In C we can write exactly the same thing by hand: a <code>struct</code> with data, a <code>const struct</code> with function pointers, and a <code>void *context</code> as the replacement for <code>this</code>. Keep this in mind, the whole article is built on it. C++ does not give you a new ability here, it only writes the boilerplate for you and checks it at compile time.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="s---single-responsibility-principle">S - Single Responsibility Principle<a href="https://embedbits.cz/blog/solid-principles-c-cpp#s---single-responsibility-principle" class="hash-link" aria-label="Direct link to S - Single Responsibility Principle" title="Direct link to S - Single Responsibility Principle" translate="no">​</a></h2>
<blockquote>
<p>A module should have one, and only one, reason to change.</p>
</blockquote>
<p>The "reason to change" is the important part. It does not mean "a class has one method". It means that each part of the code answers to one source of changes: when the sensor is replaced, only the conversion changes, when the customer wants another log format, only the formatting changes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c">In C++<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c" class="hash-link" aria-label="Direct link to In C++" title="Direct link to In C++" translate="no">​</a></h3>
<p>The following class does everything: it reads the ADC, converts the value, formats the text and sends it. Four reasons to change in one place:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">TemperatureMonitor</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint16_t</span><span class="token plain"> rawValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">AdcRead</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                                </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 1. hardware access</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rawValue </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.3f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4095.0f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.5f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">100.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 2. conversion</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">24</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">snprintf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">sizeof</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"T=%.1f C\r\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 3. formatting</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">UartSend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                                                     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 4. communication</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>Every change (a new sensor, a CAN log instead of UART, a different text format) edits the same class, and nothing of it can be tested without the hardware. The fix is to separate the responsibilities and let the monitor only connect them:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">AdcChannel</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">uint16_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">AdcRead</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Tmp36Converter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ToCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint16_t</span><span class="token plain"> rawValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rawValue </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.3f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4095.0f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.5f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">100.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">UartLogger</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">24</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">snprintf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">sizeof</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"T=%.1f C\r\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">UartSend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">TemperatureMonitor</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> logger</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">converter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">ToCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">adc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    AdcChannel   adc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Tmp36Converter converter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    UartLogger   logger</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-1">In C<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-1" class="hash-link" aria-label="Direct link to In C" title="Direct link to In C" translate="no">​</a></h3>
<p>Exactly the same mistake is possible, and common, in plain C, where it usually looks like one long function in <code>main.c</code>:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Monitor_Run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token plain"> rawValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Adc_Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                                </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 1. hardware access</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rawValue </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.3f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4095.0f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.5f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">100.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 2. conversion</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">24</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">snprintf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">sizeof</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"T=%.1f C\r\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 3. formatting</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">                                                     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 4. communication</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The tool for separation in C is the <strong>module</strong>: a pair of files <code>.h</code>/<code>.c</code> with a common prefix, where the header is the public interface and everything else is <code>static</code>. One module, one responsibility:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Tmp36.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">TMP36_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">TMP36_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Converts a raw ADC value of the TMP36 sensor into degrees Celsius. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Tmp36_Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token plain"> rawValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Tmp36.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Tmp36.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Tmp36_Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint16_t</span><span class="token plain"> rawValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rawValue </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.3f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4095.0f</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.5f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">100.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Logger.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">LOGGER_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">LOGGER_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Logger_Print_Temperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Logger.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Logger.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Logger_Print_Temperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">24</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">snprintf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">sizeof</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"T=%.1f C\r\n"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The ADC module (<code>Adc.h</code>) is the same idea and the monitor only wires the modules together:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Monitor.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Adc.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Logger.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Tmp36.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Monitor_Run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Logger_Print_Temperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">Tmp36_Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">Adc_Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>If the TMP36 is replaced by an NTC, only <code>Tmp36.c</code> is exchanged. If the log goes to CAN instead of UART, only <code>Logger.c</code> changes. And <code>Tmp36_Get_Celsius()</code> can be tested on your PC with a plain <code>assert</code>, because it does not touch any register.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="o---openclosed-principle">O - Open/Closed Principle<a href="https://embedbits.cz/blog/solid-principles-c-cpp#o---openclosed-principle" class="hash-link" aria-label="Direct link to O - Open/Closed Principle" title="Direct link to O - Open/Closed Principle" translate="no">​</a></h2>
<blockquote>
<p>Software entities should be open for extension, but closed for modification.</p>
</blockquote>
<p>You shall be able to add new behaviour without editing code that already works and is tested. The typical smell is a <code>switch</code> over a type that grows with every new feature.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-2">In C++<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-2" class="hash-link" aria-label="Direct link to In C++" title="Direct link to In C++" translate="no">​</a></h3>
<p>The pipeline below has to be modified for every new filter, including the <code>enum</code> and the <code>switch</code>:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">FilterType</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> MovingAverage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Median </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SamplePipeline</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">explicit</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">SamplePipeline</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">FilterType type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">filterType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Feed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">filterType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> FilterType</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">MovingAverage</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">MovingAverageStep</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> FilterType</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">Median</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">MedianStep</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// every new filter means editing this class again</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    FilterType filterType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">MovingAverageStep</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">MedianStep</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The solution is an abstraction (interface) that the pipeline knows and new filters implement:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IFilter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">IFilter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MovingAverage</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IFilter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        sum </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> sample </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">index </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">size</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">size</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">array</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">float</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sum </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Median3</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IFilter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">index </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">size</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">auto</span><span class="token plain"> sorted </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">sort</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sorted</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">begin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> sorted</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">end</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sorted</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">array</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">float</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SamplePipeline</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">explicit</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">SamplePipeline</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">IFilter</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> filterToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">filter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">filterToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Feed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> filter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// never changes again</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    IFilter</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> filter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>A new filter is a new class. <code>SamplePipeline</code> is closed for modification and the system is open for extension.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-3">In C<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-3" class="hash-link" aria-label="Direct link to In C" title="Direct link to In C" translate="no">​</a></h3>
<p>The same <code>switch</code> problem in C:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> FILTER_MOVING_AVERAGE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> FILTER_MEDIAN </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filterType_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Pipeline_Feed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">filterType_t</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> FILTER_MOVING_AVERAGE</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">MovingAverage_Step</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">case</span><span class="token plain"> FILTER_MEDIAN</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain">         </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Median_Step</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* every new filter means editing this function again */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The C replacement for the virtual table is a <strong>table of function pointers</strong> and a <code>void *context</code> for the data of the instance. The abstraction is defined once:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Filter.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">FILTER_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">FILTER_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The "interface": a table of functions and the data they work on. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">filterOps_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filterOps_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">ops</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">              </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">filter_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Filter_Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filter_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">filter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> filter</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">ops</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">filter</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<p>Every filter is a pair of the data (<code>context</code>) and a constant table with the behaviour:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">MovingAverage.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">MOVING_AVERAGE_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">MOVING_AVERAGE_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Filter.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">MOVING_AVERAGE_SIZE</span><span class="token macro property"> </span><span class="token macro property expression number" style="color:rgb(247, 140, 108)">4u</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain">    window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">MOVING_AVERAGE_SIZE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain">    sum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">unsigned</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">movingAverage_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">extern</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filterOps_t</span><span class="token plain"> movingAverageOps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">MovingAverage.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"MovingAverage.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">MovingAverage_Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">movingAverage_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">self </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">sum </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> sample </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">index </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> MOVING_AVERAGE_SIZE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">sum </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> MOVING_AVERAGE_SIZE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filterOps_t</span><span class="token plain"> movingAverageOps </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Process </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> MovingAverage_Process </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The second filter is a completely separate module, the first one was not touched:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Median3.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">MEDIAN3_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">MEDIAN3_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Filter.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain">    last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">unsigned</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">median3_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">extern</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filterOps_t</span><span class="token plain"> median3Ops</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Median3.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Median3.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Median3_Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">median3_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">self </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">index </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">index </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> second </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> third </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> self</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">last</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">first </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> second </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> second </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> third</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">||</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">third </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> second </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> second </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">second </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> third</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">||</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">third </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> first </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> second</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> first</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> third</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filterOps_t</span><span class="token plain"> median3Ops </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Process </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Median3_Process </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The pipeline knows only <code>filter_t</code>, so it never needs to change again:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Pipeline.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Filter.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Pipeline_Feed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filter_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">filter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Filter_Process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">filter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* never changes again */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>And this is how it is used. Both filters work with the same pipeline:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">movingAverage_t</span><span class="token plain"> average </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filter_t</span><span class="token plain"> averageFilter </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">movingAverageOps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">average </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">median3_t</span><span class="token plain"> median </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">filter_t</span><span class="token plain"> medianFilter </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">median3Ops</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">median </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> output </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Pipeline_Feed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">medianFilter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> sample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The tables are <code>const</code>, so they live in flash and cost no RAM. What the C++ compiler generates for <code>virtual</code> is exactly this.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="l---liskov-substitution-principle">L - Liskov Substitution Principle<a href="https://embedbits.cz/blog/solid-principles-c-cpp#l---liskov-substitution-principle" class="hash-link" aria-label="Direct link to L - Liskov Substitution Principle" title="Direct link to L - Liskov Substitution Principle" translate="no">​</a></h2>
<blockquote>
<p>Objects of a subtype must be usable wherever the base type is expected, without the caller noticing the difference.</p>
</blockquote>
<p>This is the least understood principle. It is not about the syntax (the compiler checks that for you), it is about the <strong>contract</strong>. A derived class must not require more than the base class promises and must not deliver less. If the caller needs an <code>if (typeid(...))</code>, the principle is broken.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-4">In C++<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-4" class="hash-link" aria-label="Direct link to In C++" title="Direct link to In C++" translate="no">​</a></h3>
<p>Three storage devices behind one interface. Which of them violates the contract?</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IStorage</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">IStorage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Eeprom</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IStorage</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// any address, any length</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Flash</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IStorage</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">||</span><span class="token plain"> length </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// stronger precondition than the base class promised</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ProgramDoubleWords</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RomImage</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IStorage</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">throw</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">logic_error</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"ROM is read-only"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// the caller never expected an exception</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p><code>Flash</code> requires aligned addresses and lengths, which the base class never mentioned, so code that stores five bytes works with <code>Eeprom</code> and silently fails with <code>Flash</code>. <code>RomImage</code> throws an exception in a system that probably builds with <code>-fno-exceptions</code>. All three compile, and only one behaves.</p>
<p>The fix is to honour the contract in the implementation, and to not inherit when the capability is not there:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IReadable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">IReadable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IWritable</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IReadable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Contract: any address, any length inside the device. Returns false only on a real failure.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Flash</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IWritable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Honours the contract: unaligned parts are merged with the current content (read-modify-write).</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ProgramWithPadding</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RomImage</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IReadable</span><span class="token base-clause">   </span><span class="token base-clause comment" style="color:rgb(105, 112, 152);font-style:italic">// cannot write, so it is not an IWritable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-5">In C<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-5" class="hash-link" aria-label="Direct link to In C" title="Direct link to In C" translate="no">​</a></h3>
<p>C has no inheritance, so is the principle irrelevant? On the contrary, a table of function pointers is an interface exactly like in C++ and the substitution problem is the same. In C it is even more dangerous, because the typical violations are a <code>NULL</code> in the table or an <code>assert</code> in the implementation:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">bool</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">bool</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> bool </span><span class="token function" style="color:rgb(130, 170, 255)">Flash_Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">assert</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> length </span><span class="token operator" style="color:rgb(137, 221, 255)">%</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* the caller was never told */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Flash_ProgramDoubleWords</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token plain"> flashStorage </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Read </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Flash_Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Write </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Flash_Write </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token plain"> romStorage   </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Read </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Rom_Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Write </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">NULL</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* callers crash */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Settings_Save</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> storage</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">SETTINGS_ADDRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* NULL call or failed assert */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The cure is the same as in C++, plus one habit: <strong>write the contract down in the header</strong> and make all implementations obey it. No <code>NULL</code> in the table, no assert for a caller's mistake, no hidden precondition:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Storage.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">STORAGE_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">STORAGE_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stddef.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    STORAGE_OK</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    STORAGE_ERROR_READ_ONLY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    STORAGE_ERROR_RANGE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    STORAGE_ERROR_DEVICE</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageStatus_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/*</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> * Contract of every storage implementation:</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *  - Read and Write are never NULL.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *  - Write accepts any address and any length inside the device. Alignment is the problem</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *    of the implementation, not of the caller.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> *  - Writing to a read-only device does not crash, it returns STORAGE_ERROR_READ_ONLY.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageStatus_t</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageStatus_t</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Storage.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageStatus_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Flash_Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Unaligned head and tail are merged with the current content (read-modify-write). */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Flash_ProgramWithPadding</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageStatus_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Rom_Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> STORAGE_ERROR_READ_ONLY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token plain"> flashStorage </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Read </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Flash_Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Write </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Flash_Write </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token plain"> romStorage   </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Read </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Rom_Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Write </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Rom_Write   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">storageStatus_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Settings_Save</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">storageOps_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> storage</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">SETTINGS_ADDRESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* works with every implementation */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p><code>Settings_Save()</code> works with the flash, the ROM image (it gets a normal error code) and with any implementation that appears later.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="i---interface-segregation-principle">I - Interface Segregation Principle<a href="https://embedbits.cz/blog/solid-principles-c-cpp#i---interface-segregation-principle" class="hash-link" aria-label="Direct link to I - Interface Segregation Principle" title="Direct link to I - Interface Segregation Principle" translate="no">​</a></h2>
<blockquote>
<p>Clients should not be forced to depend on methods they do not use.</p>
</blockquote>
<p>A "fat" interface couples everyone to everything. When the UART gets a new method, every client and every mock has to be recompiled and reviewed, even though they only wanted to send bytes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-6">In C++<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-6" class="hash-link" aria-label="Direct link to In C++" title="Direct link to In C++" translate="no">​</a></h3>
<p>The logger needs one method, but depends on five:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IUart</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">IUart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> baudrate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">SetParity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Parity parity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">EnableDma</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> enable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">        </span><span class="token function" style="color:rgb(130, 170, 255)">Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t </span><span class="token function" style="color:rgb(130, 170, 255)">Receive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t maxLength</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Logger</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">explicit</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Logger</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">IUart</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> uartToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">uartToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// needs one method, depends on five</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token generic-function function" style="color:rgb(130, 170, 255)">reinterpret_cast</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token generic-function generic class-name keyword" style="color:rgb(255, 203, 107);font-style:italic">const</span><span class="token generic-function generic class-name" style="color:rgb(255, 203, 107)"> </span><span class="token generic-function generic class-name keyword" style="color:rgb(255, 203, 107);font-style:italic">uint8_t</span><span class="token generic-function generic class-name" style="color:rgb(255, 203, 107)"> </span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">*</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">strlen</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    IUart</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The interface is split by the role of the client. Configuration stays on the concrete class, and the logger asks only for the ability to write bytes:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IByteSink</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">IByteSink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IByteSource</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">IByteSource</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t </span><span class="token function" style="color:rgb(130, 170, 255)">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t maxLength</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Uart</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IByteSink</span><span class="token base-clause punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token base-clause"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IByteSource</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint32_t</span><span class="token plain"> baudrate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">          </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// configuration stays on the concrete class</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">SetParity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Parity parity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">EnableDma</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> enable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t </span><span class="token function" style="color:rgb(130, 170, 255)">Read</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">size_t maxLength</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Logger</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">explicit</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Logger</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">IByteSink</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> sinkToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">sink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sinkToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// exactly what it needs</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> sink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token generic-function function" style="color:rgb(130, 170, 255)">reinterpret_cast</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token generic-function generic class-name keyword" style="color:rgb(255, 203, 107);font-style:italic">const</span><span class="token generic-function generic class-name" style="color:rgb(255, 203, 107)"> </span><span class="token generic-function generic class-name keyword" style="color:rgb(255, 203, 107);font-style:italic">uint8_t</span><span class="token generic-function generic class-name" style="color:rgb(255, 203, 107)"> </span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">*</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> std</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">strlen</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    IByteSink</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> sink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>A mock for the logger test has now one method instead of five.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-7">In C<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-7" class="hash-link" aria-label="Direct link to In C" title="Direct link to In C" translate="no">​</a></h3>
<p>The fat interface exists in C as a huge struct of function pointers or, more often, as one giant header file <code>Uart.h</code> that everybody includes:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> baudrate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">SetParity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uartParity_t</span><span class="token plain"> parity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">EnableDma</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool enable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Receive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> maxLength</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">uartDriver_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Log_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uartDriver_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* needs Send, receives five functions */</span><br></div></code></pre></div></div>
<p>There are two tools. The first is the same as in C++: a small interface (<code>byteSink_t</code>) that carries only what the client needs:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">ByteSink.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">BYTE_SINK_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">BYTE_SINK_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stddef.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdint.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">byteSink_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Log.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">LOG_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">LOG_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"ByteSink.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Log_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">byteSink_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">sink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Log_Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Log.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Log.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;string.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">byteSink_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">logSink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Log_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">byteSink_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">sink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    logSink </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> sink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Log_Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">char</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    logSink</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">Write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">logSink</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">strlen</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The second one is specific for C: <strong>split the header</strong>. Everyone who only sends bytes includes <code>Uart_Tx.h</code> and nobody else sees the configuration:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Uart_Config.h  - used by the code that sets the peripheral up */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uart_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> baudrate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Set_Parity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uart_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uartParity_t</span><span class="token plain"> parity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Uart_Tx.h      - used by everybody who only sends */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Send</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uart_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> length</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Uart_Rx.h      - used by everybody who only receives */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Uart_Receive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">uart_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">uart</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint8_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token plain"> maxLength</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The logger can be tested with a three-line function that captures the bytes. It does not know that a UART exists.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="d---dependency-inversion-principle">D - Dependency Inversion Principle<a href="https://embedbits.cz/blog/solid-principles-c-cpp#d---dependency-inversion-principle" class="hash-link" aria-label="Direct link to D - Dependency Inversion Principle" title="Direct link to D - Dependency Inversion Principle" translate="no">​</a></h2>
<blockquote>
<p>High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details.</p>
</blockquote>
<p>This is the principle that connects the other four. It is the one behind the layers from the article about <a class="" href="https://embedbits.cz/blog/design-architecture">design and architecture</a>: the application must not know which register toggles a LED.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-8">In C++<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-8" class="hash-link" aria-label="Direct link to In C++" title="Direct link to In C++" translate="no">​</a></h3>
<p>The thermostat (a high-level policy) contains the ADC and GPIO classes (low-level details). It cannot be compiled without the hardware, cannot be tested on a PC and cannot be moved to another board:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Thermostat</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Update</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> adcSensor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">ReadCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// knows the ADC</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">20.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> gpioHeater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">On</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// knows the GPIO pin</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">22.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> gpioHeater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Off</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    AdcSensor  adcSensor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// concrete low-level classes inside a high-level policy</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    GpioHeater gpioHeater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>After the inversion, the policy owns the interfaces and the drivers implement them. The arrow of the dependency points to the policy:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">before:   Thermostat ───▶ AdcSensor, GpioHeater</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">after:    Thermostat ───▶ ITemperatureSensor, IHeater</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                                ▲                ▲</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                                │                │</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                          AdcSensor         GpioHeater   (or a fake in the test)</span><br></div></code></pre></div></div>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ITemperatureSensor</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">ITemperatureSensor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ReadCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IHeater</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">~</span><span class="token function" style="color:rgb(130, 170, 255)">IHeater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">virtual</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Thermostat</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// high-level policy: knows only the abstractions</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">ITemperatureSensor</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> sensorToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> IHeater</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> heaterToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">sensor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">sensorToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">heaterToUse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Update</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> sensor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">ReadCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">20.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">22.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token boolean" style="color:rgb(255, 88, 116)">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    ITemperatureSensor</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> sensor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    IHeater</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">            heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">AdcSensor</span><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">ITemperatureSensor</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">ReadCelsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">GpioHeater</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause keyword" style="font-style:italic">public</span><span class="token base-clause"> </span><span class="token base-clause class-name" style="color:rgb(255, 203, 107)">IHeater</span><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Set</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">bool</span><span class="token plain"> on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">override</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-c-9">In C<a href="https://embedbits.cz/blog/solid-principles-c-cpp#in-c-9" class="hash-link" aria-label="Direct link to In C" title="Direct link to In C" translate="no">​</a></h3>
<p>C offers two ways, and the second one is unique for C and cheaper than any virtual call.</p>
<p><strong>1. Runtime injection</strong> with function pointers, exactly like in the open/closed example. The interface belongs to the thermostat (it is in <code>Thermostat.h</code>), the drivers fill it:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Thermostat.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">THERMOSTAT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">THERMOSTAT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* The thermostat owns the interface, the drivers implement it. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> bool on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">   </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">thermostatPorts_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Update</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">thermostatPorts_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Thermostat.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Thermostat.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Update</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">thermostatPorts_t</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> ports</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">ports</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">20.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> ports</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">ports</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">22.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> ports</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">ports</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>In the unit test you pass functions that return a number and remember the heater state. On the target you pass <code>Adc_Get_Celsius</code> and <code>Gpio_Set_Heater</code>, and <code>Thermostat.c</code> stays untouched.</p>
<p><strong>2. Link-time injection.</strong> Sometimes you do not need to switch implementations at runtime, you only need to make a decision once, in the build system. Then the abstraction is a <strong>header with declarations</strong> and the implementation is a source file that CMake picks for the target:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">Bsp_Thermostat.h</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">ifndef</span><span class="token macro property"> </span><span class="token macro property expression">BSP_THERMOSTAT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">define</span><span class="token macro property"> </span><span class="token macro property macro-name">BSP_THERMOSTAT_H</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">&lt;stdbool.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Implemented by the BSP of the board - or by a fake in the unit test. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">endif</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_OeMC">ThermostatLink.c</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"Bsp_Thermostat.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Thermostat_Update</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">float</span><span class="token plain"> celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_Celsius</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">20.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">celsius </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">22.0f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_Heater</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>For the board, <code>Bsp_Thermostat_Stm32.c</code> is linked and implements both functions with the real peripherals. In the unit test on the PC, <code>Bsp_Thermostat_Fake.c</code> is linked instead. No function pointers, no indirection, no RAM, and the thermostat is still completely independent of the hardware. This is, by the way, exactly what the BSP of Embedbits does: the application calls an interface of the BSP and does not care which family or which board is behind it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-same-ideas-in-two-languages">The same ideas in two languages<a href="https://embedbits.cz/blog/solid-principles-c-cpp#the-same-ideas-in-two-languages" class="hash-link" aria-label="Direct link to The same ideas in two languages" title="Direct link to The same ideas in two languages" translate="no">​</a></h2>



































<table><thead><tr><th>Principle</th><th>C++</th><th>C</th></tr></thead><tbody><tr><td><strong>S</strong></td><td>class</td><td>module (<code>.h</code>/<code>.c</code> pair, prefix, <code>static</code>)</td></tr><tr><td><strong>O</strong></td><td>abstract class, <code>virtual</code>, <code>override</code></td><td><code>const</code> table of function pointers + <code>void *context</code></td></tr><tr><td><strong>L</strong></td><td>contract of the base class</td><td>contract written in the header, no <code>NULL</code> in the table</td></tr><tr><td><strong>I</strong></td><td>several small interfaces</td><td>small structs of pointers, split headers</td></tr><tr><td><strong>D</strong></td><td>constructor injection of an interface</td><td>function pointers in a <code>struct</code>, or link-time injection</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-compiler-does-not-do-for-you">What the compiler does not do for you<a href="https://embedbits.cz/blog/solid-principles-c-cpp#what-the-compiler-does-not-do-for-you" class="hash-link" aria-label="Direct link to What the compiler does not do for you" title="Direct link to What the compiler does not do for you" translate="no">​</a></h2>
<p>Honesty is due. C++ has advantages that you have to replace by discipline in C:</p>
<ul>
<li class=""><strong>No compile-time check.</strong> If a field of the function table is forgotten, the compiler stays silent (designated initializers at least name the fields, and in C a missing one becomes <code>NULL</code>). Use <code>.Process = ...</code> initializers, never positional ones, and have a unit test that calls every function of each implementation.</li>
<li class=""><strong><code>void *context</code> is not type safe.</strong> A wrong cast will not be found by the compiler. Keep the cast in one line at the beginning of each function (<code>movingAverage_t *self = context;</code>) and nowhere else.</li>
<li class=""><strong>Costs.</strong> An indirect call is a few cycles and the tables cost flash. On a Cortex-M this is usually irrelevant, but not in an interrupt that runs every 10 microseconds. There, the link-time variant is free.</li>
</ul>
<p>And the biggest trap: <strong>SOLID is a set of guidelines, not a law</strong>. Splitting a 30 line function into five modules with function pointer tables because "the principle says so" is its own kind of spaghetti. Apply a principle when there is a real reason to change, a second implementation, or a unit test that cannot be written without it. Not before.</p>
<p>If you remember one sentence from this article, let it be this one: <strong>the principles are about the direction of dependencies and the size of the pieces, not about classes.</strong> C++ gives you classes, C gives you modules and function pointers. The good design needs neither of them to be fancy.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="Architecture" term="Architecture"/>
        <category label="C" term="C"/>
        <category label="C++" term="C++"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Design & Architecture]]></title>
        <id>https://embedbits.cz/blog/design-architecture</id>
        <link href="https://embedbits.cz/blog/design-architecture"/>
        <updated>2024-09-29T20:59:52.000Z</updated>
        <summary type="html"><![CDATA[OCD. Three great letters that force me to always think about software architecture. That can be really painful, especially if I have to deal with "Arduino" style architecture. You surely know it: the whole project in a few folders, the application in the src folder, the low level functionality in the driver folder and so on. But what to do in complex systems?]]></summary>
        <content type="html"><![CDATA[<p>OCD. Three great letters that force me to always think about software architecture. That can be really painful, especially if I have to deal with "Arduino" style architecture. You surely know it: the whole project in a few folders, the application in the <em>src</em> folder, the low level functionality in the <em>driver</em> folder and so on. But what to do in complex systems?</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="modularity">Modularity<a href="https://embedbits.cz/blog/design-architecture#modularity" class="hash-link" aria-label="Direct link to Modularity" title="Direct link to Modularity" translate="no">​</a></h2>
<p>Every group of functionality shall be encapsulated in a package. By connecting such packages we get more and more complex systems. Imagine a project where you want to measure a temperature with a sensor connected to the ADC and send the actual data through the UART. We need a module that reads the raw data from the ADC, calculates the value in °C and provides it on its interface, and another module that handles the communication through the UART.</p>
<p>If we combined all of this functionality in a single place, we would determine the position and the speed of an elementary particle at the same time. That would cause the collapse of the wave function and the destruction of the universe (sarcasm).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="abstraction-layers">Abstraction layers<a href="https://embedbits.cz/blog/design-architecture#abstraction-layers" class="hash-link" aria-label="Direct link to Abstraction layers" title="Direct link to Abstraction layers" translate="no">​</a></h2>
<p>Imagine a tree. The top of the tree is a single point that handles or executes the needed functionality. In embedded systems it can be an infinite loop in the main function or some RTOS handler. The lower the tree goes, the wider it gets. This represents the connections and the hierarchy between the modules. The roots of the tree represent the connections to the hardware.</p>
<p>The basic example is the "blinky": the LED connected to PA1 shall be active if the button connected to PA0 is pressed, and vice versa.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="font-style:italic">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:rgb(195, 232, 141)">"stm32g4xx_ll_gpio.h"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">while</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">LL_GPIO_IsInputPinSet</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIOA</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> LL_GPIO_PIN_0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token function" style="color:rgb(130, 170, 255)">LL_GPIO_SetOutputPin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIOA</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> LL_GPIO_PIN_1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token function" style="color:rgb(130, 170, 255)">LL_GPIO_ResetOutputPin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIOA</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> LL_GPIO_PIN_1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>We have mixed all the layers in this example. It can be acceptable for a primitive project, but in a complex system it leads to anarchy, mess, spaghetti code <strong>and the end of the world</strong>. To avoid a miserable, long and crucial armageddon, humans invented a few awesome things, like hierarchy and abstraction layers. In my projects I separate the functionality into three basic layers: Application, Middleware and Board Support Package (a.k.a. BSP). These are also split into multiple layers to achieve portability and modularity.</p>
<p><img decoding="async" loading="lazy" alt="Folder structure of a project: Application, Artifacts, Bsp (Hal, LinkerFiles, Mcal, Ral, Startup), Docs and Middlewares" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUkAAAIWCAMAAADtZI8lAAAAtFBMVEUAN9oBPc8CQsQDSLkETq4FU6QGWZkHXo0IZIQJankKb20LdWIMDAwMfFcNJQwNgkkOOQwPSAwPijoQVQwRYQwRawwRdAwRlCcSfgwShgwTHTIToQ4UkAwUmQwUoQwVqwwVtAwWvQwWxgwZKk8dNGUhISEhO3cjQoUmSJIpTp8rUqstWLYvXMAxYcszZdU1a+E3b+o5dPU7eP9FRUVUVFRubm6Dg4OMjIyUlJSdnZ3CwsLMzMzWqPBxAAAaxklEQVR42u2dCVfbypaFS7M8CCUmiQAFAk4uIQ5hcKe73+v3//9X13iqbE0eEyztWutyhVQy8KUm1dY5m01RDlPY2/p1Ft93qbPJXbv9rLdP8mZee/r78qHzVqqzWG5x124/65gk39/M55/PxNH5nJfzujrnF+80rvn8TlXekOTTS+3p+8XXmjpEUp35uXzd6i8Rdz0tl8vXx6va6z9eGi9VP4t/zpYk393dXlze3cjDi4vP9SQv9OmbuahysznJ++WP+n64vK+pY0jqMy9PTq3uIu96Wi4Wj8unWpDLF37pebMPe+BVtyR5eXf27v3H+Xvd+LpI8i+f55uTfHy96iRp6xiS6sy35ffXn1v8JfKuJ/ERj8u6668vV+JHPGz8D8OmN18+3s1vBJsPt7ozmgN76eOt6tS3l+/v5oaUJHkj2pz8cvGF9+ZbzlEVQ/Ku9pPFpU/yc37/3//q3+br8qf4lR5fXx9eX79On54fXpdP3/ifo4qtM716XC5/LtwzvA1dPb7ojiYrP4mmJr4sly/fnvl/vOm8LJe6w6q7FEkxKtAlfXC/XMhaj/ZzKnXoNzQk5ze8D37hf+X89uJadEY6WLl0eccP5ufXdx8u559qSH6af7m4uPjIR8mb+Wd+pHv33cf6T+Z3Xc8F3P/+z781yZ/Lr+JXevq+/LXgf8jT8kn2r/vF0/JxsVjYOvLS08vSOSP+1gdx9MBr/hK9kgiI2x9/8lPfeYf9+fq88jm8d78+TO0lc/BddQPe8+lzKnXoNySS71QflAfiy+qBuPTlVrTL+ft38/Mvl9Oz+UUNyWvT553eLWac8/pP5pPX/FpW+69/1G1Xr4/yV1pMl4t7SfKr7nq2d6s6V3JoUyTVGX5qwVvQD12Jt2inLYl/FtH8nkWbfVh+s3epGYd/OF0yB4sqyUod5zfUJOUfz9vbjaZAB/aSKuccnaBYS/LD3fzL5YfKOPlp/rH2k3ljv3u/NsZ/WyNpBkNL0tYRzcqe4e2EN9vXXxLk8+u36SpJdbseJe7tXfJH/OCDIV0yBw9VkpU6zm+4Ocnrc1HO3vM2+Vm0yfO5YPbBkPwivpx9/HwrhgI9/plphV+r+2Re1mb1l6dpA8kfRNLWMSTVGd4yzFiqQSoCzyskf92LcmXvkj9CVKJL5kD9iCszTorPqdRpJFnfB+WlL3d6VTg/5wPf5/nFO9kzr0Udzu6MoFyKLn7OmyGRPLu9afjka/mvQb37Yfm9ieS9mUJ1na/LX6Z36zNT2Ry/82+unjW3p2czDBiSzzTtm7vkj7jiWOkSHdDcTZ9TrdNEsmFeEJfO+Xh3cXE5nd5dvBNz9wXHcMNnlmsxjF5f3NzcfppeXIr5RczUZ3d3/Pi9nHEubnnl+k/m1dwZ5/ll2kSSD3w/F4tvVIdf+qVnHH3mm2LNmxCfWhZyenoUdZ5efqgJ66v86Fc+BPycup/Dq77wn0WX6GBh1pPmc2rq0G+o1pOEq2GtIi+dX/Pe+Jlzuz07k6Pb2eXd/O6S1zm7nt+d887KkfL55VpePBfrofeqC99dtqyCLu0qyLS7OpLT+2fec7/Ztnn1S6+CzJmFnsBf7CqI13m9598taHCc3vPbOGz7ObKyXIaaS/bAPOOYz6mpQ7/hLs848y8fzz8c40n81+vVDnU2uWu3nyVa+OKYz928Uc3nA9kFen35etS9oPfn7wey4/hgHqxOcX/ybZWviy36NytNAbg99ydBEiRBEiRRQBIkQRIkUUASJEESpZ5kXoDkQUiOWQSSByGZeQlIYpwESZBEAcljk+T//f7P/7RXKo9fQBIkQfKtkcwYYyF9M+pG1lBnOCQT5tUSmKWpTyQ9ljXgS2cddYZD0g+bKJUhkRxFRX2V1N7cUGcwJHM2kY+U7SQbS9r4zzA4kiNWxL6gFow9FkycAyIpRky1Os0ixvyU93zGvCgTHFVx60x85sWF/pww7w3Jf/2uKw5JTmvM+FgXMj9JPG9mD4gkHzFDppB6SRqwsTgT+7w1ZvxCnKapU2fCUUdiqgpZmMYs6A3J+mJJFizlLWwk/vBM7MKN7IHbu1NJKWK54KlOFSxZ7d2qTqj+WWbqIGaDaZMT0aa8SPzxggPnSgdVkp75vhiFYSjXSBWSdFZ+TsoGM07GZqDbimTAe3kqmY1AUpMUzZE3zInq1BNJUh8Yuuu9W4yXE9G7Q3k4buzdgyKZKxAs5n94wCcaSUAfiEU7nzTycixmkzTNytwTY0HMB9YwmwSBz8fSwhPN06njzDiDIplKYmXo8z987DNfrILMAcckFj2in8rCW2keefwMn5B4jXEklz1ZwC/lTh1aBQ2sd9tVOFs/wA4GSIIkSIKkLEfaDZ72p4AkSIIkSO6uUJTlLOZr9SgHyemeCsXMY1EaswQkp3sqFKF8bp+hd29IslGhmLHYkNOP2xmLPW/sebNBktxdociY0bjNFlDGwgnv8CwdJMndFYqMhk+zLZnxuizNBkpyd4UikxvC7lb5sEnurlDM5HvsILkpyRaFIjTiA3r3ngpFzqfwNI1GzowDko2lVaGYxT5jwdhZBYHkBs/d2+xhgiRIgiRIDpEkdByQBEmQBMkGkjuoDyBZS3IH9QEk60juoj6AZB3JXdQHqjMkkkdRH6jOkEgeRX2gOmiTluRO6gPVwThpSe6kPoBkDcmd1AeqA5JUdlMfqA5IUtlNfaA6ILnn/iTVAUmQBEmQxP4k9idBEiRBEiShPkB9eGMkoT78BfWhZMzPA/6fTEzA+JkhkTyk+lCKXExxwgJ5JvGCQZE8pPogtntT+YAT+DKheo42aUluoz7YXEw65VqGcdKS3EZ9cEhGmSgFSFqS26gPlmTgFZi7V8t26oPM/jdTiQH5oJCApC1bqQ8qI2VmklVy/CC57/4kVuYgCZIgif1JRJGAJEiCJEgako3qg04NH4LkdE/1IWWpKGOQnO6pPqQMvXsbks3eEERSpj4XX/pj97ADyT28IWpI9sbuYQeSe3hDqHFytkKyL3YPR2iTLd4QtInmkOxLGvMjjJMt3hCrvTsAyXaSLeqDJRloJwiQbC5t6gORjFmUhqE/AsmW0qY+EMkiYl4W8iEAJDd57kZuFpAESZAEyXaSeDsaJEFy4CRX7adB0iXZqD4wlpQ5o7co6+ynQdIl2ag+CKe70TrJVftpkHRINqsPLGGzMFojiXGykWSz+sDSIGVjuROsfKit/XTfXKePrD6wdOT54m1z40Nt7af75jp9ZPWBpTlLzHv7hY4VcwxqY4Y2uZn6IBkKktaH2pIclJvqdE/1gUhaH2qQbCbZoj4Yko4PNUg2ljb1wZC0PtRkPw2SldKmPlDvJh9qsp8GyQPtT2JlDpIgCZLYn4SOA5IgORSSjuiAt1maSDaqD3IdrhMvOaIDSDaRbFQfxINhLDYqV0UHkGwg2ZZ5ST4tJtWQCJCsI9msPujttdCKDkXMWJLiPfNt1QciuSI6hD5D7MOW6oOkN1G9W25Lqj1KH21yW/VBzjhMzTgp0ztsYq7HOFk3TraoD2IV5OlVEEjul3lpLYZRZbXyQbKutKkPRNIRHaLhzjh7qA/OPpsWHYpowKsgvB0NkiAJkiB5IJLY6QVJkARJkGwg2ez7kPqMRRlIbkqyUX0Ys0CoDwVITvdUHyLGIRYztMkNSTarDzHLdduUThpiyzcNmIjSGSTJPdSHjHky5Xbpia3yEec6Emm50zHUhy3VhzIPGUsKMSdxoJEn+ns+1N79z+/fu6sPYpc8ZIHu2MLjZcK7fTIZJMnO0qY+yJKIZsjbo9hW5/PPOPaHmVetm2SL+lAokvK7cUyLzqQPZi6HJ9mmPvhBIrTFUq45fWHglCby/Ra0yZrSpj4kAWmLKZPEY602gmTbc3f7/mTsFcNemR+K5Hg1yhskdyOZxYFYC4Hk3iRTLxwN+7m7PHSZ9rCAJEj2kSSFM2R83RiBZDvJirKQpbP1HEo585I6S4KVyoMnWVEWUvu9CWcwG7p1dgUZSCqSVWUhrWo2YVCCZBdJoywYt2jt08KcHEo6W3lp0ytJL0XfJIaXtfonOqyR3FhZMG7RysQzTW0OpSxNfV96ElB6pUyMmwEb28o9FB3WSG6sLJBbtNthU2bdhPRZmV5JSQyZ07t7KDps2SZJWbAA10na3k3plbxwfZzsoeiw5TgZ24HOABw1kqT0SpYkVe6f6LAlSVIWLMmMjetJ2vRKEa2KnMp9Ex22I0nKgnWLLgtPNL3chjMYkja9Uu6JQSF2KvdQdNiOJCkLjlu0fDTkjY7CGah3U3qlMo88seaxlXsoOmAHAyRBEiRB8pAkQRskQRIkD1VOMMz2cCSdJXqT6LCJMAGSMtlFqh4bW/bVO7fTQbLuLSCQ3I9kIJKwRMxRKIxm0SpM8Md1Fhenm5TpcLEPoTFEnnlhOWKj0ooORrNoEyYmHGziBaeblOlwsQ8h7RNNWCw3NN0N9pReuGoQJgJfvhOYn2xSpkO2Sfu2KfOLsk6qaBEmjAx0sqmEjjLjJJrkaJ1kizDBokyUAiQdkhOWqNeDSHTQJNuEiUC/NX2ySZmOsJ40Mw6JDqRZtAkTfA7iZ5LyZJMyHeEZx6yCSHSwmkWLMCHXRSJ87FSTMmEHAyRBEiRB8lRJntq/CEiC5OBIpuyIlMQLxeHKQR9I1lpLK5Iy43FctFOZxR6ZQ2ykUJTyhWI/XDnoB8kaa2lDUmThDttBevwpMWbJ5vvqKy9tOgenT7LeWjo1mTHi9m4eqlxCJUhaa+ly4qu+bHQETdLTf638ooMgbJMUj9x6K0nfbgypa1QMqlND0qgYpvLp7fSStbTQESLRl42OoF1dxg5JEwThzB0j2pNzbheG1DUqBtWpkiQVw1Q+PfWBrKVDlchqRjqCnnEyh2S0Hk6WUQc2t5MhdY2KQXWqJI2KQZVPsU1qGwIJMHV0BNW7R3wgJJImCMIhaQZYczsZrdaoGFSnStIGs+jKpzhOtpMsg1D9tUFogyCccTJqJjnahqRWMfpA0nQ90hEUk4Iv+ERkY0HLocTt4qFRKpzebQ03VlWMld69lisioNwvp0/SmTIiO+OkPr8UizOhP6IgCFtyT0xC0ci9nex01lQMd8ZJxLyU2wOjYlDlEyZpV0ERrYLElJPIM17Gv6MgiJVnHL58CcbOKohIVlQMZxUkfoifOQdaxaDK2MHADgZIgiRIgmS/AkxAEiSHQTIbtYsFLXVAsslaulYsaKkDkk3W0k1b3E11QLLJWrqRJMbJVpIr1tLk+0CKAJFcrRPmts4ASG72nvmqtbT2fSBFwOa5cu2nhcRAdQZAsjv2oVy1lra+D1YRcHq3qaMlBlOn9yS7fR8q1tLWrcBJb1UlqQ9Nnd6T7CxVa2mHJCkCLSR1HZCsWktb3werCDi11kiaOiBZay2tfR8oroE0AqeOJmnqgGSNtTT5PlBcA2kETh2SvVQdkKx91Qc7GCAJkiA5EJIDy0YFkiAJkiC5Pcnm4AUQ3JZkU/ACCG5Lsil4AQR3Iek5MQtGWQDBVZKbZFWSwQsUs2CUBRBcJblJViUZvEAxC0ZZAMFt26QOXqCYBbMfDoI7jJMyaMHELIDkHiQL8yZKIlPrK2UBBLdfT8rgBYpZMMoCCG7/jCODFyhmwSgLILjvc7fZewRBkARJkARJVbCHCZIgCZLVSAeQ3I6kpJY5AQ0U6QCSe5KktyVBEiT/Mklr7gCStSQ7s9wIz+lYkDTmDiBZT7Iz81LFdRokd2yTpneTuQNI7jlOkrkDSO5H0po7mH0OkNyNpDV3MJEOILlj77bmDjrSASSxgwGSIAmSIHlaOaxAEiRB8u+TXMuqtGGwmLzrDTg4/G2SLq61rEotJHXa95DuegMODm+J5FpWpVaS0ltw7N4VgmSzp0O5jekLSDrq7GpWpZCSkq+bMliSdFfVwcEEXPSF5MYOv9WsSvLbiBVVUwZLku6qOjiYgIu+kNwo81J9ViVxKRd54iumDHqcnK309HUHBxNwMbg2Wc1gEzKRkymvMWUonRzl6ySpsgm4GOKMUyGpFzoVU4aVGWedJFXWARcgKQ8iIUpUTBnqSa47OOiAi+GQ1K7T1axK4qDwOJiKKYMlSXdVHBwo4GI4JCmZ0npWJb0KSqqmDJYk3VVxcKCAC+xgYAcDJEESJEFyQ5LTPheQBMkhkhxGEMTRXacHEwRxdNfpwby6f3TXaZDcniS5TovnZT8tBxYEcQTX6Yx5SRqw8cCCII7gOq3EAi14DycI4giu054RWYcVBHEEX1oiOawgiCOQNFLgwIIgjkAy91jM55pyYEEQx3CdziNP5qgcVhAEdjBAEiRBEiT/PsnpIApIguSASCLz0q4rc8d1GpmX9iLpp2miXaeRL2gvkmGpXGhB8hAkxXM3Mi91kNwoy82Et0lkXuog2ak+qHGyQOalvdukKH5eIvPSIcbJWETgIPPSAUhmLC6Reekgc3fIZsi8dKBVUIzMS9jBAEmQBEmQ/FskhyHxgCRIgiRIdpJMfcbkvmSWzhoDSpougaQlOWaBiGd3MjPUpgfKQLKLpMhiUxazEiT3JRnrF1B1pjTmxD6YPEv2ktxuE1/64159uJ3ejHlyEFQ5LtK0tDKEybNkL1mSvXGvPpz6UOYhY0mx1oWVDGHyLNElh2Rf3Ks3JfnP798dbVI0x1Dk/iJcVoYgtjUk++K5vCnJzmJtlFUuupXYByI5ckkGIFlLslAkRXYaNl6LfSCS+hKfaPSl/rhXH46kHyQie1opkyzxxpiTDGHzLJlLfKKP0jD0Rz1yrz4cySTQhtS85Yl8kTnJEG4WOn2piJjHR1XWI/fqA4+TW5f++NuCJEiC5KBJDj5CBCRBEiRBcpO4hmAMkgcg6aeJLxK9guS+JEOZJD8DyYOQnIlGOfGZJ70YTHql0zBl+GMkN4prKP1QejFE6u1dnV7pNEwZ/hjJzrgG89a4tHIQXyi90mmYMryxNhmEJe3bUlKg0zBleFvjZMGiGpKnYcrwtkjGfFRc690nY8rwltaTqS8MbmjGMemVTsSU4W0948goWVoFmfRKp2HKgOdukARJkATJ/pDE29EgCZInT9JxlCYTMH7Q4hYNku7K3Ho6OI7SLskWt2iQdElaTwfHUdol2eJxDJIOyXpPB5DcnqTxdCBv6II/bycCIB1U3KJHLBeJmHifrwRBnJqj9OYkN/Z0WHGUDn3mHFTcojOWjb2kZHE1COLUHKU3J7mxp4PpyeqlZw6QDqpu0TmbpPyUHhNWgyBOzFF6U5LdcQ02V7kmqY4TZg9q3KJZGk14S85qgiBOzFF6U5KdZUuSxi2apeHMy3ijqwZBnJij9BFJzsQGuujUdFDjFh3GrAwl7UoQxIk5Sh+BpOMoHZkZJzIzzrpbdBgEZcxHxJogiBNzlD4CSfKGFjmV1CooolXQult0ytur7NQ1QRCn5Sh9OJLYwQBJkARJkOwqh90NnvawgCRIDomkif8Cye1IVuMjQHJHkpX4CJDckWQlPgIk9yAp4yOMshAykVUpczKxCKki5g/pwya5VXyEVBZMjgs3p42SKoZNcuP4CFIW5KvUcgdJkySpAm1ys/gIoyyYXEBEkjbYMU52jpMyPsIoC5JkbkgGILkNSREfYdUHVqrIJ5NniaQKkOxYT6r4CKs+MHEmKd08SxFmnC3iI1xlIZwoWULlWTJSBUgeZAcjAsnDkCy8ACT3JjkWkiybgOTeJFPGfPHSGkjuRnI6iAKSIAmSINlFclj7uiAJksMkafIS9Flr2Idk104vkaRcGX3WGvYh2aU+EEmTv6XXWsMfaZPmhfJe75D/kXESJA9F0vTuXmsNxyWZipK5M06EGWcnkjoswq6Ceqw1/IXn7ggkD0Oyr1rDnyXZZ63hz5Lss9bwF8bJwbxwDpIgOTiSKQPJLUm62ZnWSIpFu8qkCpJbZmeqkOTrodpcYSBZR7I5O5Pc3IgZSG5I0mRnWlEfEkvSc4IgeugWccD3zE12por6oHq3N3ZI9tAt4oCxDyY7U0V90DOOG5jTQ7eIQ7ZJnXWksmeuevdIpOg3JHvoFnHIcbKdpAh+ILPpHrpFHIFkRX1QJAs/tGbTPXSLOALJivqghAmfX6IgiB66RRyBZEV9UMKElzhBED10i8AOBkiCJEiC5FskOe1hAUmQBEmQ7H4vaGTz8K6WijABku0kg2aSa8IESLaS9FjeRHJdmADJVpJhGAuSuUymL3d9Y88be96MhAlyghg2yc73zMOxJ9ukzBeUCGjhhEXCn8AIE+QEMWySnbEPYemNBcmR6OF+oHZ9U/VVCRPkBIE22d4myzgSJAsW8849WiFpttO1EwTGyfZxkvOLRXuMPN65Z/UklRMESHaQLH1pMjZmEz8q60gaJwiQ7CI5Ul4EXsDG9SS1EwRIdpEsFMmYeWUtSeMEAZJ47gZJkARJkDwgyemwCkiCJEiCZCfJ1GcsyspU544OQXJHkmMWiNfPikzGOaTpGCR3JBkx8XrarCSPS5DckWSsXx0HyS6SXTu9GfOkvSdIdpHsUh/KPGQsKUBy7zYpCErNGyQPsZ5M5GAJknuRLBTJDCT3JekHSao2y0FyP5JJoMIZQBLP3SAJkiAJkn+Y5MA8vkESJAdA0k0Rn422zcUEkiQ6rJD0at47XyEpA5ajvJZcZnbphkWSRIcVkqOo6CIpQ+Zn9YnEsoH2bvWQ2GIAUUtS3piAZC3JscfCXHzPi47HyQP+n83FtDaoSn9Q/tSeOZXNcFGOxcuY/HrSF5LdO71EMuQdPeB/fJoqUPx/cZzwU5SLqYYk7+W+aISmciYO0pR/pBfKJDl5X0h2qg+W5EymjHZ6sggl4edtLqZVkhPduwv5f13Z9u5EfqDXk979z+/fm7dJF6E74tkMQqszDuMzTjEKw9CkGlodJ2cCMIt7QrKz7ExS72oGXpKmqyRH5oC3x8mbz0H9R0naXEyVZXzGSemkTEQyk1ON7P1jkSlwuCTHYsZJ00zNHbPSycVUITljYTYJAn9kK5eFJ9qpWLX7oR8PmaRxglDrmax0cjFVHy3HPvPH/LKtzD9QJKnMVWb08ZBIbl4yRnYbm5VY+NSDZLXM0lRbwGxWxicgsf0dkts14DhQr3aA5J4l9cJROSCSgy8gCZJvrfw/ScJr6XVl0eYAAAAASUVORK5CYII=" width="329" height="534" class="img_ev3q"></p>
<p>The <em>Application</em> contains what the product does. The <em>Middleware</em> contains reusable software without hardware dependency, like a logger, a ModBus stack or a non-volatile memory manager. And what is the BSP? Easy. It contains everything needed for communication, configuration and handling of the hardware. From our example above, the GPIO operations belong to the BSP. The user shall not care about the exact connection of the button and the LED, so the interface between the BSP and the application can look like <em><strong>Bsp_Get_ButtonState()</strong></em> and <em><strong>Bsp_Set_LedState()</strong></em>. If anything changes in the hardware, nobody has to edit multiple places and only the BSP is updated.</p>
<p>So the BSP contains at least one layer of encapsulation for these getters and setters. But what will they use? Will they write to the registers directly? I don't think so. STMicroelectronics has two sets of "drivers": the "HAL" and the "LL". Why the apostrophes? Because neither name is correct. Their "HAL" package is in reality a huge and slow spaghetti code which has nothing in common with its description, because HAL stands for Hardware Abstraction Layer. We will get to the real one at the end.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="register-abstraction-layer-ral">Register Abstraction Layer (RAL)<a href="https://embedbits.cz/blog/design-architecture#register-abstraction-layer-ral" class="hash-link" aria-label="Direct link to Register Abstraction Layer (RAL)" title="Direct link to Register Abstraction Layer (RAL)" translate="no">​</a></h2>
<p>The functions <code>LL_GPIO_xxx</code> from the example are an encapsulated access to the registers of the MCU. You can write register operations everywhere, but what if you change the MCU or make a mistake? You have to fix it in every single place. That would be painful, so we have just found the lowest abstraction layer, the <em>Register Abstraction Layer</em>. It represents only the abstraction of the registers, encapsulated in (usually inline) functions with meaningful names.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">__STATIC_INLINE </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">LL_GPIO_SetOutputPin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_TypeDef </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain">GPIOx</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">uint32_t</span><span class="token plain"> PinMask</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">WRITE_REG</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIOx</span><span class="token operator" style="color:rgb(137, 221, 255)">-&gt;</span><span class="token plain">BSRR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> PinMask</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The name "LL" is from my point of view incorrect (same as their HAL, but who would use that?), but we get access to all registers with a meaningful description, so we can use it without difficult manual writing.</p>
<p>In my projects the RAL consists of three parts:</p>
<ul>
<li class=""><strong>CMSIS</strong> by ARM: the definitions of the Cortex-M core,</li>
<li class=""><strong>CMSIS_ST</strong> by STMicroelectronics: the device headers with the register definitions and the system initialization of the MCU family,</li>
<li class=""><strong>RAL_ST</strong>: the original LL drivers of ST together with my <code>Port</code> layer. The <code>Port</code> layer provides a unified naming that does not depend on the MCU family, so the code above the RAL does not change when the MCU does.</li>
</ul>
<p>The RAL knows registers and nothing else. It does not know that something is connected to PA1.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="microcontroller-abstraction-layer-mcal">Microcontroller Abstraction Layer (MCAL)<a href="https://embedbits.cz/blog/design-architecture#microcontroller-abstraction-layer-mcal" class="hash-link" aria-label="Direct link to Microcontroller Abstraction Layer (MCAL)" title="Direct link to Microcontroller Abstraction Layer (MCAL)" translate="no">​</a></h2>
<p>So we have easy access to the registers. But what shall be next? Accessing a GPIO is trivial, but what about the other peripherals? For a transfer through the UART we need multiple registers for every operation: activate the peripheral, set the baudrate, the bit length, the parity, the stop bits and so on. And because we already know that every functionality which is used more than once shall be encapsulated, we create functions for reading errors, starting a transfer, writing to the output data register, reading the input data register and many more.</p>
<p>This functionality cannot be the RAL, because it is hierarchically higher and calls the RAL. It takes care only of the peripherals of the microcontroller, so the name of this layer is <em>Microcontroller Abstraction Layer</em> (MCAL). The user sees <code>Gpio_Set_PinLevel()</code> or <code>Usart_Send()</code> and does not need to know a single register. One peripheral, one interface: if the I2C needs the DMA, the I2C module handles it internally.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hardware-abstraction-layer-hal">Hardware Abstraction Layer (HAL)<a href="https://embedbits.cz/blog/design-architecture#hardware-abstraction-layer-hal" class="hash-link" aria-label="Direct link to Hardware Abstraction Layer (HAL)" title="Direct link to Hardware Abstraction Layer (HAL)" translate="no">​</a></h2>
<p>Now we can initialize all peripherals of the MCU: RCC, DMA, USART/UART and so on. But the configuration has to be compatible with the devices connected on our PCB. So we are not focusing only on the MCU, but on the whole circuit. Thus we need another abstraction layer, the <em>Hardware Abstraction Layer</em> (HAL). Yes, this is the real meaning of the name, not like the "HAL" of ST.</p>
<p>The HAL is the only point of the interface between the application (or the middleware) and the hardware. It knows which pin is the LED, which UART is connected to the debug connector and how the peripherals are configured. To achieve the needed functionality it connects multiple modules from the MCAL. This is the last abstraction layer of the BSP.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="board-support-package">Board Support Package<a href="https://embedbits.cz/blog/design-architecture#board-support-package" class="hash-link" aria-label="Direct link to Board Support Package" title="Direct link to Board Support Package" translate="no">​</a></h2>
<p>The BSP is the hardware oriented package which contains everything necessary for the initialization and the usage of all peripherals of the MCU and of the connected circuit. Besides the three layers above it also contains the <strong>startup</strong> code (initialization of the memory sections and the call of the application) and the generation of the <strong>linker</strong> script for the selected MCU. Each STM32 family has its own branch, so the interface of the BSP stays the same and only the content below it changes.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Application / Middleware</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">────────────────────────</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          HAL            what is connected to which pin, how the board is configured</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          MCAL           peripherals: Gpio, Usart, I2c, Dma, ...</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          RAL            registers: CMSIS, ST LL drivers, unified Port layer</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">────────────────────────</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">         Hardware</span><br></div></code></pre></div></div>
<p>The rule is simple: <strong>a layer calls only the layer directly below it.</strong> The application never includes an ST header, the MCAL does not know which pin is the LED, and the RAL does not know which peripheral is used for what.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-blinky-again">The blinky again<a href="https://embedbits.cz/blog/design-architecture#the-blinky-again" class="hash-link" aria-label="Direct link to The blinky again" title="Direct link to The blinky again" translate="no">​</a></h2>
<p>Let's rewrite the example. The application does not know any hardware:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">while</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_LedState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_ButtonState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>The BSP knows the board and uses the MCAL. The pins are described in a single table, so a new revision of the PCB changes one line and nothing else (simplified, the error handling is omitted):</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PortId_t</span><span class="token plain"> portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinId_t</span><span class="token plain">  pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">   </span><span class="token class-name" style="color:rgb(255, 203, 107)">bspPin_t</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">bspPin_t</span><span class="token plain"> bspButton </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> GPIO_PORT_A</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_0 </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">bspPin_t</span><span class="token plain"> bspLed    </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> GPIO_PORT_A</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> GPIO_PIN_1 </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bool </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Get_ButtonState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token class-name" style="color:rgb(255, 203, 107)">gpio_PinLevel_t</span><span class="token plain"> pinLevel </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO_PIN_LEVEL_LOW</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Get_PinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bspButton</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> bspButton</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">pinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">GPIO_PIN_LEVEL_HIGH </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> pinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Bsp_Set_LedState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bool isActive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token function" style="color:rgb(130, 170, 255)">Gpio_Set_PinLevel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bspLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">portId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> bspLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">pinId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                          isActive </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> GPIO_PIN_LEVEL_HIGH </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> GPIO_PIN_LEVEL_LOW</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>And somewhere at the bottom, inside <code>Gpio_Set_PinLevel()</code>, the RAL function <code>LL_GPIO_SetOutputPin()</code> finally writes the <code>BSRR</code> register. Four layers for a blinking LED looks like a nonsense, and for the blinky it is. But the point is what happens when the product grows:</p>
<ul>
<li class=""><strong>A new MCU family:</strong> another branch of the BSP is checked out, the application is not touched.</li>
<li class=""><strong>A new revision of the PCB:</strong> the LED moves to another pin, one line in the HAL changes.</li>
<li class=""><strong>A unit test of the application:</strong> the BSP is replaced by a fake one and the application runs on a PC, without any hardware.</li>
<li class=""><strong>A bug in a register access:</strong> it is in exactly one place.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-find-it">Where to find it<a href="https://embedbits.cz/blog/design-architecture#where-to-find-it" class="hash-link" aria-label="Direct link to Where to find it" title="Direct link to Where to find it" translate="no">​</a></h2>
<p>All layers described here are open source and documented, each of them in its own repository of the <a href="https://github.com/Embedbits" target="_blank" rel="noopener noreferrer" class="">Embedbits</a> organization:</p>
<ul>
<li class=""><a class="" href="https://embedbits.cz/docs/bsp">BSP</a>: the package with the startup, the linker script and the HAL,</li>
<li class=""><a class="" href="https://embedbits.cz/docs/bsp/ral">RAL</a>: CMSIS, CMSIS_ST and RAL_ST,</li>
<li class=""><a class="" href="https://embedbits.cz/docs/bsp/mcal">MCAL</a>: the peripheral modules together with the table of supported STM32 families,</li>
<li class="">the <a class="" href="https://embedbits.cz/docs/platform/embi-platform/coding-style">coding style</a> that makes the names in these layers readable.</li>
</ul>
<p>If you want to see the same idea from the point of view of the language, read the article about the <a class="" href="https://embedbits.cz/blog/solid-principles-c-cpp">SOLID principles in C++ and C</a>. The layers above are nothing else than the <em>dependency inversion</em> applied to the whole firmware.</p>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
        <category label="Architecture" term="Architecture"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Finite state machines]]></title>
        <id>https://embedbits.cz/blog/finite-state-machines</id>
        <link href="https://embedbits.cz/blog/finite-state-machines"/>
        <updated>2024-09-29T16:24:40.000Z</updated>
        <summary type="html"><![CDATA[For embedded software development is propper design necessary. Microcontroller has to handle processing of application itself and communication with plenty of connected circuits through internal or external peripherals. The execution of application shall be as fast as possible. But that is really terrible explanation for anyone. In real world, the developer has to ensure optimal short logical path of code execution. Which means, that developer shall not check all the conditions during each main cycle. The one way of this optimization, is to correct nesting of conditions. This can be really difficult with increasing complexity of project. A lot of nested conditional statements can lead to unstability of code and making code less readable. The code readability is cruel necessary for future updates, or for maintenance of existing code. One of my beloved quote says:]]></summary>
        <content type="html"><![CDATA[<p>For embedded software development is propper design necessary. Microcontroller has to handle processing of application itself and communication with plenty of connected circuits through internal or external peripherals. The execution of application shall be as fast as possible. But that is really terrible explanation for anyone. In real world, the developer has to ensure optimal short logical path of code execution. Which means, that developer shall not check all the conditions during each main cycle. The one way of this optimization, is to correct nesting of conditions. This can be really difficult with increasing complexity of project. A lot of nested conditional statements can lead to unstability of code and making code less readable. The code readability is cruel necessary for future updates, or for maintenance of existing code. One of my beloved quote says:</p>
<!-- -->
<p><img decoding="async" loading="lazy" alt="Excerpt of a state machine routine table in C" src="https://embedbits.cz/assets/images/fsm-state-machine-cc3162be67be4421b1cac2bb42f51afd.png" width="551" height="586" class="img_ev3q"></p>
<blockquote>
<p><strong>Always code as if the guy, who end up maintaining your code will be a violent psychopath who knows where you live.</strong></p>
</blockquote>
<p>So we should better think before writing actual code. This process is called “design” and i really like it. Because if you do it right, the amount of new code and subsequent editation of this new code is really reduced. Sometimes you could think it take so much time, but in reality, is this time summed with time of writing code shorter than writing code which will be continuously rewritten. But how to make it easier? Here we can start to talk about Finite State Machines also known as FSM.</p>
<p>So lets start with AI generated meaningless description:</p>
<blockquote>
<p>State machines, particularly Mealy and Moore machines, are fundamental models in the design of digital systems and computational theory. Both of these machines are used to represent systems that transition between different states based on inputs and produce outputs as a result. However, the way they handle output generation is what sets them apart.</p>
<p>A <strong>Mealy machine</strong> produces outputs based on both the <strong>current state</strong> and the <strong>current input</strong>. This makes Mealy machines more responsive, as the output can change dynamically with each input signal.</p>
<p>On the other hand, a <strong>Moore machine</strong> generates outputs solely based on its <strong>current state</strong>, independent of the input. This makes Moore machines simpler and more predictable, as the output remains constant until the state changes.</p>
<p>These state machines are widely used in embedded systems, control systems, and digital circuits where precise state transitions and outputs are critical. In this blog, we’ll explore how Mealy and Moore machines function, their key differences, and how they can be applied in practical system design.</p>
</blockquote>
<p>But what does it mean? In simple way, the Mealy finite stae machine is checking the conditions for required state <em><strong>before</strong></em> the actual state execution. The Moore state machine is checking the conditions <em><strong>after</strong></em> the actual state execution.</p>
<p>But what the state represent? Imagine a light bulb which can be turned on and off by pressing a button. For handling of this behavior, our state machine would need only two states. One state which activates the actuator, and another state which this actuator deactivates.Really simple, isnt it? But what in complex systems? Well, you need a simple implementation which is applicable for various situations. That is what the template below does.</p>
<p>During my work at automotive industry, we have faced with my colleague <a href="https://www.linkedin.com/in/jano-sima/" target="_blank" rel="noopener noreferrer" class="">Jan Sima</a> the problems with Finite State Machines designs. There has been plenty of different styles but none of them had sufficient functionality to reach stability and clean design. So we decided to design own template. With permission of Jan, i am publishing the template of our Finite State Machine under MIT license.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="download-the-template">Download the template<a href="https://embedbits.cz/blog/finite-state-machines#download-the-template" class="hash-link" aria-label="Direct link to Download the template" title="Direct link to Download the template" translate="no">​</a></h2>
<p>The template is published under the MIT license. Everything is plain text, so you can read it before you download it:</p>

























<table><thead><tr><th>File</th><th>What it is</th></tr></thead><tbody><tr><td><a href="https://embedbits.cz/downloads/fsm/FsmTemplate.c" target="_blank" rel="noopener noreferrer" class="">FsmTemplate.c</a></td><td>The template in <strong>C</strong> (C99), one file with the states, the table of the routines and the stubs</td></tr><tr><td><a href="https://embedbits.cz/downloads/fsm/FsmTemplate.hpp" target="_blank" rel="noopener noreferrer" class="">FsmTemplate.hpp</a> and <a href="https://embedbits.cz/downloads/fsm/FsmTemplate.cpp" target="_blank" rel="noopener noreferrer" class="">FsmTemplate.cpp</a></td><td>The template in <strong>C++</strong> (C++17), a class with one state machine inside</td></tr><tr><td><a href="https://embedbits.cz/downloads/fsm/Fsm.hpp" target="_blank" rel="noopener noreferrer" class="">Fsm.hpp</a></td><td>The header-only engine for the C++ version (no heap, no exceptions, no RTTI)</td></tr><tr><td><a href="https://embedbits.cz/downloads/fsm/fsm-instantiate.sh" target="_blank" rel="noopener noreferrer" class="">fsm-instantiate.sh</a></td><td>A small script that replaces the names, <code>fsm-instantiate.sh Button FsmTemplate.c src/</code> creates <code>src/Button.c</code></td></tr></tbody></table>
<p>The names in angle brackets are replaced by the name of your module: <code>&lt;Module&gt;</code> becomes <code>Button</code>, <code>&lt;module&gt;</code> becomes <code>button</code> and <code>&lt;MODULE&gt;</code> becomes <code>BUTTON</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://embedbits.cz/blog/finite-state-machines#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>It is a Moore machine. Every state has four routines and the machine calls them in the same order on every run:</p>
<ol>
<li class=""><strong>Entry</strong>: called once, when the state is entered.</li>
<li class=""><strong>Execute</strong>: called on every run, here is the work of the state.</li>
<li class=""><strong>CheckLeave</strong>: called on every run after Execute. This is the <strong>only</strong> place where a new state is requested.</li>
<li class=""><strong>Leave</strong>: called once, when the state is left.</li>
</ol>
<p>The whole engine is one function. This is the C version:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">Module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">_HandleStateTransition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">void</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* A corrupted actual state must not index outside of the table: start again from the default state. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">MODULE</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_STATE_COUNT </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">MODULE</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_STATE_1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_NewState    </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">MODULE</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_STATE_1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">Module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">_CallRoutine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_StateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Actual state is in the valid range */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Execute function shall be used for main execution of actual state */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">Module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">_CallRoutine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_StateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">execute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* CheckLeave function shall be used for check leave condition of actual state */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">Module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">_CallRoutine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_StateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">checkLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* In case of an invalid request (made in checkLeave), switch to the default/error state. */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">MODULE</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_STATE_COUNT </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_NewState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_NewState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">MODULE</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_STATE_1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Requested state is in the valid range */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Leave and entry functions shall be executed only in case if the state has to be changed to another state */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_NewState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">Module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">_CallRoutine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_StateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">leave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_NewState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">Module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token function" style="color:rgb(130, 170, 255)">_CallRoutine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_StateRoutines</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">module</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">_SM_ActualState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* No new state required */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Because a transition is requested only in <code>CheckLeave</code>, the entry and the leave of a state are executed always as a pair, in a known order, and the outputs depend only on the state. A routine that is not needed can be <code>NULL</code> (<code>nullptr</code> in C++) and it is skipped.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-was-fixed">What was fixed<a href="https://embedbits.cz/blog/finite-state-machines#what-was-fixed" class="hash-link" aria-label="Direct link to What was fixed" title="Direct link to What was fixed" translate="no">​</a></h2>
<p>The first version of the template that I published here had a few mistakes. I went through it again, built it and ran it against a test that records the order of the calls. These are the changes:</p>
<ul>
<li class="">The initial value of the state variables was a leftover name from another project (<code>APPCORE_HANDLER_STATE_1</code> instead of <code>&lt;MODULE&gt;_STATE_1</code>).</li>
<li class="">The last row of the table used <code>State_2_Leave</code> instead of <code>State_3_Leave</code>. The code compiled and called the wrong routine when the third state was left. The table is now indexed by the state (<code>[&lt;MODULE&gt;_STATE_3] = { ... }</code>), so the position of a row cannot be confused.</li>
<li class=""><code>Init</code> did not run the entry routine of the first state.</li>
<li class="">The state numbers were not checked. A corrupted actual state or a request of a nonexistent state indexed outside of the table. Both are checked now and the machine falls back to the first state, which is the safe one. The request is checked <strong>after</strong> <code>CheckLeave</code>, because that is the place where it is made. My first fix of this checked it before, and the test caught that, which is a nice proof of why such a test is worth it.</li>
<li class="">A routine with the <code>NULL</code> pointer is skipped instead of crashing.</li>
<li class="">A missing forward declaration, and a header comment that turned into nonsense after the names were replaced.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-c-version">The C++ version<a href="https://embedbits.cz/blog/finite-state-machines#the-c-version" class="hash-link" aria-label="Direct link to The C++ version" title="Direct link to The C++ version" translate="no">​</a></h2>
<p>In C++ the same pattern is a class. The state is an <code>enum class</code>, the routines are private member functions and the table is <code>constexpr</code>:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Button</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">public</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">enum</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">State</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token base-clause">std</span><span class="token base-clause double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token base-clause keyword" style="font-style:italic">uint8_t</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> Idle </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0u</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Pressed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Count </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Init</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">noexcept</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">Task</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">noexcept</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    State </span><span class="token function" style="color:rgb(130, 170, 255)">GetState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">noexcept</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> stateMachine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">GetState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">using</span><span class="token plain"> Machine </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> fsm</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">StateMachine</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">Button</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> State</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token generic-function function" style="color:rgb(130, 170, 255)">static_cast</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token generic-function generic class-name" style="color:rgb(255, 203, 107)">std</span><span class="token generic-function generic class-name double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token generic-function generic class-name" style="color:rgb(255, 203, 107)">size_t</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">State</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">Count</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">IdleEntry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">IdleExecute</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">IdleCheckLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain">   </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">IdleLeave</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">PressedEntry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ... */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">constexpr</span><span class="token plain"> Machine</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">Table </span><span class="token function" style="color:rgb(130, 170, 255)">MakeTable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">noexcept</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> Machine</span><span class="token double-colon punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">Table table</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    Machine stateMachine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>A request is <code>stateMachine.RequestState(State::Pressed)</code> in a <code>CheckLeave</code> routine. The row of the table has to belong to its state, and this is checked at <strong>compile time</strong> with a <code>static_assert</code>, so the mistake from the first version cannot even be built. There is no heap, no exception and no RTTI, so it fits the usual embedded and MISRA-like restrictions. The C++ version was compiled with <code>-Wall -Wextra -Wconversion -pedantic -fno-exceptions -fno-rtti</code> and ran under the address and undefined behavior sanitizers with the same scenarios as the C version: the order of the calls, a request, an invalid request, a corrupted state and the skipped <code>NULL</code> routines.</p>
<p>The second part of this series, <a class="" href="https://embedbits.cz/blog/fsm-in-practice-button">a button with debounce and long press</a>, shows the template in a real module.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="license">License<a href="https://embedbits.cz/blog/finite-state-machines#license" class="hash-link" aria-label="Direct link to License" title="Direct link to License" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Copyright (c) 2024 Marek Petrinec, Jan Sima</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">Permission is hereby granted, free of charge, to any person obtaining a copy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">of this software and associated documentation files (the "Software"), to deal</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">in the Software without restriction, including without limitation the rights</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">copies of the Software, and to permit persons to whom the Software is</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">furnished to do so, subject to the following conditions:</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">The above copyright notice and this permission notice shall be included in all</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">copies or substantial portions of the Software.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">SOFTWARE.</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>Mr.Nobody</name>
            <uri>https://embedbits.com</uri>
        </author>
        <category label="Embedded" term="Embedded"/>
    </entry>
</feed>