<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>EmbedBits Blog</title>
        <link>https://embedbits.cz/cs/blog</link>
        <description>EmbedBits Blog</description>
        <lastBuildDate>Wed, 07 Oct 2026 20:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>cs</language>
        <item>
            <title><![CDATA[Ladění HardFaultu na Cortex-M: od záhady k řádku kódu]]></title>
            <link>https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m</link>
            <guid>https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m</guid>
            <pubDate>Wed, 07 Oct 2026 20:00:00 GMT</pubDate>
            <description><![CDATA[Každý embedded vývojář zná ten okamžik v osmi registrech na zásobníku a ve čtyřech stavových registrech. Stačí je jen přečíst.]]></description>
            <content:encoded><![CDATA[<p>Každý embedded vývojář zná ten okamžik: firmware běžel, a pak najednou neběží. Debugger ukazuje, že program sedí v nekonečné smyčce se jménem jako <code>HardFault_Handler</code> nebo <code>Default_Handler</code>, a call stack tvoří pár nic neříkajících rámců. Ta smyčka je <strong>výchozí</strong> handler ze startup kódu a o tom, co se stalo, neříká absolutně nic. Chyba má ale příčinu a procesor si ji už zapsal: v osmi registrech na zásobníku a ve čtyřech stavových registrech. Stačí je jen přečíst.</p>
<p>Tento článek ukazuje, jak z té smyčky získat řádek zdrojového kódu, na dvou skutečných příkladech, které jsem spustil v QEMU (model desky se STM32F4) a prozkoumal pomocí GDB: volání ukazatele na funkci s hodnotou <code>NULL</code> a zápis na adresu, kde nic není. Všechny výstupy jsou skutečné.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-jádro-udělá-když-nastane-chyba">Co jádro udělá, když nastane chyba<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#co-j%C3%A1dro-ud%C4%9Bl%C3%A1-kdy%C5%BE-nastane-chyba" class="hash-link" aria-label="Přímý odkaz na Co jádro udělá, když nastane chyba" title="Přímý odkaz na Co jádro udělá, když nastane chyba" translate="no">​</a></h2>
<p>Cortex-M nepadá tiše. Když procesor nemůže pokračovat (neplatná instrukce, chyba sběrnice, nepovolený přístup), vyvolá <strong>výjimku</strong> a udělá dvě věci důležité pro ladění:</p>
<ol>
<li class=""><strong>Uloží osm registrů na zásobník</strong>: <code>R0</code>, <code>R1</code>, <code>R2</code>, <code>R3</code>, <code>R12</code>, <code>LR</code>, <code>PC</code> a <code>xPSR</code>. Uložený <code>PC</code> je instrukce, která chybu způsobila, a uložený <code>LR</code> říká, kdo chybující funkci zavolal.</li>
<li class="">Nastaví <strong>bity ve stavových registrech chyb</strong>, které říkají, o jaký druh chyby šlo: <code>CFSR</code> (configurable fault status, složený ze tří částí pro memory, bus a usage fault), <code>HFSR</code> (hard fault status) a adresní registry <code>MMFAR</code> a <code>BFAR</code> s adresou, ke které se přistupovalo.</li>
</ol>
<p>Memory, bus a usage fault mají své vlastní handlery, ale po resetu jsou <strong>zakázané</strong>, takže každá chyba je <em>eskalována</em> na HardFault. Proto jediný handler vidí všechno a bit <code>FORCED</code> v <code>HFSR</code> říká, že k tomu došlo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="handler-který-čte-registry">Handler, který čte registry<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#handler-kter%C3%BD-%C4%8Dte-registry" class="hash-link" aria-label="Přímý odkaz na Handler, který čte registry" title="Přímý odkaz na Handler, který čte registry" translate="no">​</a></h2>
<p>Jediná potíž je dostat se na zásobník, kde registry leží. Jádro má dva ukazatele zásobníku (<code>MSP</code> pro výjimky a hlavní kód, <code>PSP</code> pro úlohy operačního systému) a bit 2 hodnoty v <code>LR</code> při vstupu do výjimky říká, který z nich byl použit. To je nutné udělat <em>dříve</em>, než překladač použije zásobník pro své účely, takže handler je krátká funkce v assembleru (<code>naked</code>: bez prologu), která předá ukazatel funkci v 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>Podívejte se na tři části. Struktura <code>stackFrame_t</code> je rozložení osmi registrů v pořadí, v jakém je jádro ukládá. Funkce <code>HardFault_Report()</code> (spolu se stavovými registry) zkopíruje do globální proměnné <code>faultInfo</code>, vypíše krátkou zprávu a pak <strong>záměrně zůstane ve smyčce</strong>, aby se mohl připojit debugger a proměnnou si prohlédnout. Assemblerová vložka vybere správný zásobník a skočí do ní. V produktu by se zpráva zapsala do paměti, která přežije reset, a firmware by se sám resetoval, ale princip je stejný.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="příklad-1-volání-ukazatele-null">Příklad 1: volání ukazatele <code>NULL</code><a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#p%C5%99%C3%ADklad-1-vol%C3%A1n%C3%AD-ukazatele-null" class="hash-link" aria-label="Přímý odkaz na příklad-1-volání-ukazatele-null" title="Přímý odkaz na příklad-1-volání-ukazatele-null" translate="no">​</a></h2>
<p>Toto je aplikace s chybou. Callback se zaregistruje později, ale kód, který ho volá, běží dříve:</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>Program vypíše <code>start</code> a potom zprávu:</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>Teď její čtení, hodnotu po hodnotě:</p>
<ul>
<li class=""><strong><code>PC = 0x00000000</code></strong>: procesor se pokusil provést instrukci na adrese nula. Téměř vždy to znamená skok přes ukazatel na funkci s hodnotou <code>NULL</code> nebo návrat na poškozenou adresu.</li>
<li class=""><strong><code>CFSR = 0x00020000</code></strong>: bit 17 je <code>INVSTATE</code>, „invalid state". Procesor se pokusil vykonávat kód ve stavu ARM, který Cortex-M nemá. Důvod je v <strong><code>xPSR</code></strong>: jeho bit 24 je bit <code>T</code> (Thumb) a tady je nulový (<code>0x60000000</code>). Adresa funkce v Thumbu má nejnižší bit nastavený, <code>NULL</code> ho nemá, takže skok přes ukazatel bit <code>T</code> vynuloval. Nulový bit <code>T</code> je typický otisk prstu skoku na <code>NULL</code>.</li>
<li class=""><strong><code>HFSR = 0x40000000</code></strong>: bit 30 je <code>FORCED</code>, chyba byla eskalována na HardFault z usage fault, který není povolen.</li>
<li class=""><strong><code>LR = 0x08000115</code></strong>: návratová adresa s nastaveným nejnižším bitem (Thumb). Je to adresa <strong>volajícího</strong>, <code>0x08000114</code>, a právě tam je chyba.</li>
</ul>
<p>S debuggerem trvá poslední krok pár sekund. QEMU čeká na GDB (<code>-S -gdb tcp::1234</code>) a session vypadá takto:</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> vrátí funkci, <code>list *</code> řádek (ten <em>za</em> voláním, protože to je návratová adresa) a disassembly ukáže dvojici instrukcí, která je samotnou chybou: načtení nuly do <code>r3</code> a <code>blx r3</code>, volání přes registr obsahující <code>NULL</code>. Všimněte si <code>r3 = 0x0</code> v uložených registrech. Bez debuggeru je tatáž odpověď jedním příkazem toolchainu, který potřebuje jen adresu ze zprávy a soubor s ladicími informacemi (<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="příklad-2-zápis-na-adresu-kde-nic-není">Příklad 2: zápis na adresu, kde nic není<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#p%C5%99%C3%ADklad-2-z%C3%A1pis-na-adresu-kde-nic-nen%C3%AD" class="hash-link" aria-label="Přímý odkaz na Příklad 2: zápis na adresu, kde nic není" title="Přímý odkaz na Příklad 2: zápis na adresu, kde nic není" translate="no">​</a></h2>
<p>Změnil jsem jeden řádek aplikace: místo callbacku funkce zapisuje na adresu <code>0xA0000000</code>, kde v modelu čipu není namapováno nic. Zpráva:</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>Tentokrát je <code>PC</code> <strong>platná adresa ve flash</strong>, bit <code>T</code> je nastaven (<code>0x21000000</code>) a <code>CFSR</code> je jiný: <code>0x8200</code> jsou dva bity, 9 (<code>PRECISERR</code>, přesná chyba datové sběrnice) a 15 (<code>BFARVALID</code>, registr <code>BFAR</code> obsahuje adresu). V 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> je adresa, na kterou se program pokusil zapisovat, <code>PC</code> je instrukce, která se o to pokusila. Dohromady říkají „tato instrukce zapsala na tuto adresu", což je úplný popis problému. Pokud je adresa malá (<code>0x00000008</code>), jde o ukazatel <code>NULL</code> na strukturu a vy přistupujete k jejímu členu. Pokud vypadá jako data (<code>0x20000000</code> a kousek víc), jde o zásobník nebo buffer, který jste přetekli.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="bity-cfsr-se-kterými-se-setkáte">Bity CFSR, se kterými se setkáte<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#bity-cfsr-se-kter%C3%BDmi-se-setk%C3%A1te" class="hash-link" aria-label="Přímý odkaz na Bity CFSR, se kterými se setkáte" title="Přímý odkaz na Bity CFSR, se kterými se setkáte" translate="no">​</a></h2>
<p>Registr je kombinací tří registrů (každý má svůj bajt nebo dva bajty). Tohle jsou ty, které uvidíte nejčastěji (dva, které jsem pozoroval v příkladech, jsou zvýrazněny):</p>
















































































<table><thead><tr><th>Bit</th><th>Název</th><th>Význam</th></tr></thead><tbody><tr><td>0</td><td><code>IACCVIOL</code></td><td>načtení instrukce z nepovolené oblasti (MPU)</td></tr><tr><td>1</td><td><code>DACCVIOL</code></td><td>datový přístup do nepovolené oblasti (MPU)</td></tr><tr><td>7</td><td><code>MMARVALID</code></td><td>registr <code>MMFAR</code> obsahuje adresu</td></tr><tr><td>8</td><td><code>IBUSERR</code></td><td>chyba sběrnice při načítání instrukce</td></tr><tr><td><strong>9</strong></td><td><strong><code>PRECISERR</code></strong></td><td><strong>přesná chyba sběrnice při datovém přístupu: <code>PC</code> je instrukce, která ji způsobila</strong></td></tr><tr><td>10</td><td><code>IMPRECISERR</code></td><td>nepřesná chyba sběrnice: instrukce už je pryč, <code>PC</code> není spolehlivé</td></tr><tr><td>11, 12</td><td><code>UNSTKERR</code>, <code>STKERR</code></td><td>chyba sběrnice při vybírání nebo ukládání registrů (často poškozený zásobník)</td></tr><tr><td><strong>15</strong></td><td><strong><code>BFARVALID</code></strong></td><td><strong>registr <code>BFAR</code> obsahuje adresu</strong></td></tr><tr><td>16</td><td><code>UNDEFINSTR</code></td><td>nedefinovaná instrukce (provádění dat, poškozený kód)</td></tr><tr><td><strong>17</strong></td><td><strong><code>INVSTATE</code></strong></td><td><strong>pokus o provádění ve stavu ARM: skok na adresu s vynulovaným bitem 0</strong></td></tr><tr><td>18</td><td><code>INVPC</code></td><td>neplatná hodnota <code>EXC_RETURN</code> (poškozený zásobník výjimky)</td></tr><tr><td>19</td><td><code>NOCP</code></td><td>přístup k nepovolenému koprocesoru (typicky FPU, které nebylo zapnuto)</td></tr><tr><td>24</td><td><code>UNALIGNED</code></td><td>nezarovnaný přístup, je-li povolena past</td></tr><tr><td>25</td><td><code>DIVBYZERO</code></td><td>dělení nulou, je-li povolena past</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-obvykle-stojí-za-hardfaultem">Co obvykle stojí za HardFaultem<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#co-obvykle-stoj%C3%AD-za-hardfaultem" class="hash-link" aria-label="Přímý odkaz na Co obvykle stojí za HardFaultem" title="Přímý odkaz na Co obvykle stojí za HardFaultem" translate="no">​</a></h2>

































<table><thead><tr><th>Co vidíte</th><th>Co to obvykle je</th></tr></thead><tbody><tr><td><code>PC = 0</code>, <code>INVSTATE</code></td><td>volání přes ukazatel na funkci <code>NULL</code> nebo návrat na poškozenou adresu</td></tr><tr><td><code>PRECISERR</code> a malé <code>BFAR</code></td><td>ukazatel <code>NULL</code> na strukturu</td></tr><tr><td><code>PRECISERR</code> a <code>BFAR</code> v rozsahu adres periferií</td><td>přístup k nedostupné periferii, například takové, jejíž hodiny nebyly zapnuty (u některých rodin je takový přístup chybou sběrnice, u jiných se tiše ignoruje)</td></tr><tr><td><code>STKERR</code> / <code>UNSTKERR</code> nebo <code>PC</code>, které nedává smysl</td><td>přetečení zásobníku nebo bufferu, které poškodilo návratovou adresu</td></tr><tr><td><code>NOCP</code> u první instrukce s plovoucí řádovou čárkou</td><td>FPU nebylo povoleno ve startup kódu</td></tr><tr><td><code>IMPRECISERR</code></td><td>zápis, který prošel přes write buffer: zpráva přijde později než instrukce. Pro ladění lze buffering vypnout (bit <code>DISABLEDEFWRITEBUF</code> v <code>ACTLR</code>), takže chyba bude přesná</td></tr></tbody></table>
<p>První řádek tabulky a princip druhého (chyba sběrnice s adresou v <code>BFAR</code>) jsem předvedl. Zbývající řádky jsou souhrnem obvyklých příčin, vyplývají z významu bitů v referenční příručce jádra.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="praxe">Praxe<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#praxe" class="hash-link" aria-label="Přímý odkaz na Praxe" title="Přímý odkaz na Praxe" translate="no">​</a></h2>
<ol>
<li class=""><strong>Nikdy nenechávejte výchozí handler jako prázdnou smyčku.</strong> Handler výše má asi třicet řádků a promění chybu ve zprávu s místem v kódu. Vložte ho jednou do startup kódu projektu.</li>
<li class=""><strong>Uchovávejte ladicí informace</strong> v souboru, který archivujete s vydáním (<code>-g</code> a <code>.elf</code>), aby šla adresa ze zprávy z provozu převést na řádek, i když je firmware dodán bez symbolů. To je také další důvod pro <a class="" href="https://embedbits.cz/cs/blog/reproducible-builds-embedded">reprodukovatelný build</a>: adresa něco znamená jen pro přesně ten binární soubor, který ji vytvořil.</li>
<li class=""><strong>Povolte jemnější chyby</strong> (bity v <code>SHCSR</code>), když chcete mít handlery <code>UsageFault</code>, <code>BusFault</code> a <code>MemManage</code> zvlášť. Zpráva je pak bohatší, protože stavové registry nejsou sdílené.</li>
<li class=""><strong>Ukládejte zprávu do paměti, která přežije reset</strong> (sekce, kterou startup kód nemaže, viz článek o tom, <a class="" href="https://embedbits.cz/cs/blog/before-main-startup-linker">co se děje před <code>main()</code></a>), proveďte reset a po restartu ji odešlete. Zpráva ze zařízení v provozu má větší cenu než sto dohadů.</li>
<li class=""><strong>Předcházejte tomu, co jde.</strong> Volání <code>NULL</code> v příkladu je vada, kterou by zachytila <a class="" href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice">pravidla MISRA</a> a unit test modulu (ukazatel musí být nastaven před prvním voláním), a přetečení zásobníku je věc, pro kterou je nutné znát využití zásobníku (pravidlo proti rekurzi).</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="stejná-session-na-desce">Stejná session na desce<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#stejn%C3%A1-session-na-desce" class="hash-link" aria-label="Přímý odkaz na Stejná session na desce" title="Přímý odkaz na Stejná session na desce" translate="no">​</a></h2>
<p>Použil jsem QEMU, protože nepotřebuje desku, a jeho GDB server (<code>-S -gdb tcp::1234</code>) se chová stejně jako server debug probe: příkazy v příkladech jsou příkazy, které zadáváte i s probe. Platforma má artefakt pro sadu nástrojů <strong>probe-rs</strong> (ladicí sada pro cíle ARM přes debug probe, se serverem DAP), což je způsob, jak připojit GDB nebo IDE ke skutečné desce. Pro tento článek jsem ho nespouštěl, protože ve svém prostředí probe nemám.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shrnutí">Shrnutí<a href="https://embedbits.cz/cs/blog/debugging-hardfault-cortex-m#shrnut%C3%AD" class="hash-link" aria-label="Přímý odkaz na Shrnutí" title="Přímý odkaz na Shrnutí" translate="no">​</a></h2>
<ol>
<li class="">HardFault není záhada: jádro uložilo registry a nastavilo stavové bity.</li>
<li class="">Handler musí najít správný zásobník (<code>EXC_RETURN</code>) a přečíst rámec, <code>CFSR</code>, <code>HFSR</code> a <code>BFAR</code>.</li>
<li class=""><code>PC</code> a <code>LR</code> dávají místo, <code>CFSR</code> druh chyby, <code>BFAR</code> adresu.</li>
<li class=""><code>PC = 0</code> s <code>INVSTATE</code> je skok na <code>NULL</code> a bit <code>T</code> v <code>xPSR</code> to ukazuje.</li>
<li class="">Uchovejte <code>.elf</code> a adresa ze zprávy z provozu se promění v řádek kódu.</li>
</ol>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>STM32</category>
        </item>
        <item>
            <title><![CDATA[Spuštění skutečného firmwaru bez hardwaru: simulátor v CI]]></title>
            <link>https://embedbits.cz/cs/blog/firmware-in-simulator-ci</link>
            <guid>https://embedbits.cz/cs/blog/firmware-in-simulator-ci</guid>
            <pubDate>Wed, 07 Oct 2026 18:00:00 GMT</pubDate>
            <description><![CDATA[V článku o unit testování s Unity a CMock jsem řekl, že testy na PC nenajdou „rozdíly mezi PC a MCU". Tento článek je o těchto rozdílech a o nástroji, který je najde: simulátoru, který spouští skutečný binární soubor. Ne logiku přeloženou pro PC, ale přímo .elf, který vytvořil překladač ARM, se skutečným startup kódem a skutečným linker scriptem, na modelu procesoru a jeho periferií.]]></description>
            <content:encoded><![CDATA[<p>V článku o <a class="" href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock">unit testování s Unity a CMock</a> jsem řekl, že testy na PC nenajdou „rozdíly mezi PC a MCU". Tento článek je o těchto rozdílech a o nástroji, který je najde: <strong>simulátoru, který spouští skutečný binární soubor</strong>. Ne logiku přeloženou pro PC, ale přímo <code>.elf</code>, který vytvořil překladač ARM, se skutečným startup kódem a skutečným linker scriptem, na modelu procesoru a jeho periferií.</p>
<p>Ukážu dva experimenty, které jsem spustil: tentýž zdrojový kód testu, který na PC projde a na Cortex-M4 selže, a firmware, který zapisuje do registrů USART na skutečných adresách STM32F4 a jehož text se objeví v terminálu. Na konci je upřímný seznam toho, co vám simulátor neřekne.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kam-to-zapadá">Kam to zapadá<a href="https://embedbits.cz/cs/blog/firmware-in-simulator-ci#kam-to-zapad%C3%A1" class="hash-link" aria-label="Přímý odkaz na Kam to zapadá" title="Přímý odkaz na Kam to zapadá" translate="no">​</a></h2>





























<table><thead><tr><th>Úroveň</th><th>Co běží</th><th>Co najde</th><th>Rychlost</th></tr></thead><tbody><tr><td><strong>Unit test na PC</strong></td><td>logika přeložená pro PC, nižší vrstvy mockované</td><td>logické chyby</td><td>milisekundy</td></tr><tr><td><strong>Simulátor</strong></td><td>skutečný binární soubor firmwaru na modelu MCU</td><td>chyby specifické pro cíl, startup, ovladače vůči modelu registrů</td><td>sekundy</td></tr><tr><td><strong>Hardware in the loop</strong></td><td>skutečný firmware na skutečném MCU se skutečnými signály</td><td>časování, elektrické chování, skutečné periferie</td><td>minuty, laboratoř</td></tr></tbody></table>
<p>Prostřední úroveň se vynechává nejčastěji a přitom je nejlevnější na přidání do CI, které už firmware sestavuje: simulátor je spustitelný soubor, který zavoláte se souborem, který váš build vytvořil.</p>
<p>Nástrojem v mých experimentech je QEMU 8.2.2 se strojem <code>netduinoplus2</code>, modelem desky se <strong>STM32F405</strong> (Cortex-M4 s mapou paměti skutečného čipu: flash na <code>0x08000000</code>, RAM na <code>0x20000000</code>, periferie na svých skutečných adresách). Platforma má artefakt pro jiný simulátor, <strong>Renode</strong>, a k tomu se vrátím na konci.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="experiment-1-test-který-projde-na-pc-a-selže-na-mcu">Experiment 1: test, který projde na PC a selže na MCU<a href="https://embedbits.cz/cs/blog/firmware-in-simulator-ci#experiment-1-test-kter%C3%BD-projde-na-pc-a-sel%C5%BEe-na-mcu" class="hash-link" aria-label="Přímý odkaz na Experiment 1: test, který projde na PC a selže na MCU" title="Přímý odkaz na Experiment 1: test, který projde na PC a selže na MCU" translate="no">​</a></h2>
<p>Malý modul se dvěma funkcemi, které má každý firmware: převod času a kontrola přijatého bajtu.</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>Obě funkce vypadají správně a obě jsou otestovány na PC. Zdrojový kód testu je pro oba cíle stejný: liší se jen výstup. Soubor <code>Platform.h</code> tiskne přes <code>printf</code> na PC a přes <em>semihosting</em> (požadavek na simulátor nebo debugger) na cíli a návratový kód testu říká, zda prošel:</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>Na 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>Tentýž zdroj, přeložený pomocí <code>arm-none-eabi-gcc</code> pro Cortex-M4 a spuštěný v 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>Dvě chyby a obě jsou na PC neviditelné:</p>
<ul>
<li class=""><strong><code>long</code> má jinou šířku.</strong> Na 64bitovém Linuxu má <code>long</code> 64 bitů, na Cortex-M 32. <code>3 000 000 ms * 1000</code> je <code>3 000 000 000</code>, což se nevejde do znaménkového 32bitového čísla (největší je 2 147 483 647), takže výsledek je špatný a v C je to navíc nedefinované chování.</li>
<li class=""><strong><code>char</code> má jiné znaménko.</strong> Standard C nechává otevřené, zda je prosté <code>char</code> se znaménkem. Na x86 je, takže <code>(char)0xFF</code> je <code>-1</code> a kontrola <code>receivedByte &lt; 0</code> funguje. Na ARM je <em>bez znaménka</em>, takže <code>(char)0xFF</code> je <code>255</code> a porovnání nikdy neplatí. Překladač ARM to dokonce říká, a jen tam:</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>Obojí je otázka přenositelných typů, což je téma pravidla 4.6 v článku o <a class="" href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice">MISRA</a>: používejte typy s danou velikostí a znaménkem. Opravená verze používá <code>uint64_t</code> pro čas a <code>uint8_t</code> pro bajt:</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>a stejné čtyři kontroly teď procházejí <strong>na obou cílech</strong>, s návratovým kódem 0 na obou. První verze nebyla chybou testu a test na PC nebyl špatně: prostě testoval jiný program.</p>
<p>Návratový kód je celá integrace s CI. Simulátor skončí s kódem, který firmware předá volání semihostingu, takže <code>add_test</code> v CMake (viz článek o <a class="" href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware">CMake pro firmware</a>) selže, když selže test na cíli:</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-registry-periferie">Experiment 2: registry periferie<a href="https://embedbits.cz/cs/blog/firmware-in-simulator-ci#experiment-2-registry-periferie" class="hash-link" aria-label="Přímý odkaz na Experiment 2: registry periferie" title="Přímý odkaz na Experiment 2: registry periferie" translate="no">​</a></h2>
<p>Simulátor modeluje také periferie, takže může běžet i kód nejbližší hardwaru. Tohle je firmware, který posílá text přes USART1 čipu STM32F4, napsaný na úrovni registrů se skutečnými adresami (žádná knihovna, žádný startup kromě kódu z článku o tom, <a class="" href="https://embedbits.cz/cs/blog/before-main-startup-linker">co se děje před <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>Text je v terminálu simulátoru: firmware zapnul hodiny periferie v RCC, povolil USART a jeho vysílač, počkal na příznak <code>TXE</code> a zapsal datový registr, přesně jako by to udělal na desce, a model USART předal bajt na sériový port. Je to test ovladače proti modelu registrového rozhraní. Pokud ovladač čeká na příznak, který nikdy nepřijde, test to najde pomocí timeoutu, a ne u stolu s osciloskopem.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-vám-simulátor-neřekne">Co vám simulátor neřekne<a href="https://embedbits.cz/cs/blog/firmware-in-simulator-ci#co-v%C3%A1m-simul%C3%A1tor-ne%C5%99ekne" class="hash-link" aria-label="Přímý odkaz na Co vám simulátor neřekne" title="Přímý odkaz na Co vám simulátor neřekne" translate="no">​</a></h2>
<p>Simulátor je <em>model</em> a každý model má hranici. Několik, na které jsem narazil v experimentech této série:</p>
<ul>
<li class=""><strong>Časování není skutečné.</strong> QEMU provádí instrukce tak rychle, jak PC dovolí, a nepočítá cykly skutečného jádra. Test, který musí dokázat „přerušení je obslouženo do 5 mikrosekund", se v něm udělat nedá.</li>
<li class=""><strong>Přerušení přicházejí na jiných místech než na MCU.</strong> V článku o <a class="" href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data">přerušeních</a> se ztracená aktualizace sdíleného čítače v QEMU neobjevila ani při 200 000 pokusech, protože QEMU doručuje přerušení mezi bloky přeloženého kódu. Skutečné MCU může přerušit po každé instrukci. Simulátor neprokazuje nepřítomnost race condition.</li>
<li class=""><strong>Existují jen modelované periferie.</strong> Model STM32F405 má USART, ale jiný čip může mít periferii, kterou model nemá, nebo ji má zjednodušenou: registry tam jsou, analogová část ne.</li>
<li class=""><strong>Chybí elektrický svět:</strong> zákmit kontaktu, šum na vstupu ADC, pokles napětí. Vše, co přichází zvenčí, je to, co do modelu vložíte.</li>
</ul>
<p>Simulátor tedy nenahrazuje ani unit testy (jsou rychlejší a testují logiku izolovaně), ani hardwarové testy (testují realitu). Najde věci mezi nimi: překladač cíle, typy, startup, mapu paměti, ovladač proti modelu registrů, a dělá to během několika sekund při každém commitu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="renode">Renode<a href="https://embedbits.cz/cs/blog/firmware-in-simulator-ci#renode" class="hash-link" aria-label="Přímý odkaz na Renode" title="Přímý odkaz na Renode" translate="no">​</a></h2>
<p>Platforma má artefakt pro <strong>Renode</strong>, open-source simulační a virtuální vývojový framework od Antmicro, dodávaný spolu s <code>renode-test</code>, svým testovacím runnerem založeným na Robot Framework, který se používá pro integrační testy simulovaného firmwaru. Pro tento článek jsem ho nespouštěl (vydání se v mém prostředí nepodařilo stáhnout), takže pouze opakuji, co říká jeho dokumentace, a neporovnávám ho s QEMU. Struktura takového testu je stejná jako výše: skutečný ELF, model hardwaru, verdikt a návratový kód pro CI.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kontrolní-seznam">Kontrolní seznam<a href="https://embedbits.cz/cs/blog/firmware-in-simulator-ci#kontroln%C3%AD-seznam" class="hash-link" aria-label="Přímý odkaz na Kontrolní seznam" title="Přímý odkaz na Kontrolní seznam" translate="no">​</a></h2>
<ol>
<li class="">Sestavte test pro <strong>cíl</strong>, překladačem cíle, a spusťte ho v simulátoru, navíc k PC.</li>
<li class="">Používejte jeden zdroj testu pro obojí, s tenkou vrstvou (<code>Platform.h</code>) pro výstup a ukončení.</li>
<li class="">Návratový kód simulátoru je výsledek testu, takže CI nepotřebuje nic dalšího.</li>
<li class="">Používejte typy s danou velikostí a znaménkem (<code>uint32_t</code>, <code>uint8_t</code>) a varování překladače cíle: druhou chybu výše (<code>char</code>) by našlo <code>-Wtype-limits</code>, kdyby se někdo díval na výstup buildu pro ARM.</li>
<li class="">Zapište si, co simulátor dokázat nemůže (časování, race condition, analogový svět), a nechte to hardwarovým testům.</li>
</ol>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>Testování</category>
        </item>
        <item>
            <title><![CDATA[Reprodukovatelné buildy: připněte nástroje, připněte zdroje, odstraňte hodiny]]></title>
            <link>https://embedbits.cz/cs/blog/reproducible-builds-embedded</link>
            <guid>https://embedbits.cz/cs/blog/reproducible-builds-embedded</guid>
            <pubDate>Wed, 07 Oct 2026 14:00:00 GMT</pubDate>
            <description><![CDATA[Zákazník volá kvůli firmware, který jste dodali před čtrnácti měsíci. Vyberete tag, přeložíte ho, nahrajete a chyba tam není. Zmizela chyba, nebo je to jiný firmware? Pokud váš build není reprodukovatelný, nedokážete to říct. Nikdo to nedokáže, protože binárka, kterou jste právě přeložili, se od dodané liší způsoby, které nevidíte ani nedokážete vysvětlit: jiná verze překladače, knihovna aktualizovaná na PC, cesta ke složce, denní doba.]]></description>
            <content:encoded><![CDATA[<p>Zákazník volá kvůli firmware, který jste dodali před čtrnácti měsíci. Vyberete tag, přeložíte ho, nahrajete a chyba tam není. Zmizela chyba, nebo je to jiný firmware? Pokud váš build není <strong>reprodukovatelný</strong>, nedokážete to říct. Nikdo to nedokáže, protože binárka, kterou jste právě přeložili, se od dodané liší způsoby, které nevidíte ani nedokážete vysvětlit: jiná verze překladače, knihovna aktualizovaná na PC, cesta ke složce, denní doba.</p>
<p>Reprodukovatelný build má jednoduchou definici: <strong>stejné vstupy dají stejné bajty</strong>. Tento článek ukazuje, jaké jsou vstupy buildu firmware, jak je platforma Embedbits připíná (Artifacts Handler) a experiment, který jsem udělal: dva buildy stejného zdroje, ve dvou složkách ve dvou různých časech, dají dvě různé binárky. Po třech změnách pak dají tu samou, co do posledního bitu.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vstupy-buildu">Vstupy buildu<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#vstupy-buildu" class="hash-link" aria-label="Přímý odkaz na Vstupy buildu" title="Přímý odkaz na Vstupy buildu" translate="no">​</a></h2>
<p>Build je funkce. Co do ní vstupuje?</p>



































<table><thead><tr><th>Vstup</th><th>Odkud pochází</th><th>Jak ho připnout</th></tr></thead><tbody><tr><td><strong>Zdroj</strong></td><td>Git</td><td>tag nebo commit, submoduly připnuté svými commity</td></tr><tr><td><strong>Nástroje</strong> (překladač, linker, Ninja, Doxygen)</td><td>nainstalované na PC, nebo stažené</td><td>přesné verze z jednoho zdroje</td></tr><tr><td><strong>Popis buildu</strong> (flagy, linker script)</td><td>soubory CMake</td><td>v repozitáři, nic nastavené ručně</td></tr><tr><td><strong>Skripty platformy</strong></td><td>submodul EmBi_Platform</td><td>commit submodulu, aktualizovaný pomocí Updateru, záměrně</td></tr><tr><td><strong>Prostředí</strong></td><td>PC</td><td>nic na výstupu by na něm nemělo záviset: cesta, čas, jméno uživatele</td></tr></tbody></table>
<p>První, třetí a čtvrtý vstup jsou v Gitu, takže jsou připnuté už návrhem. Nástroje a prostředí jsou místa, kde se build obvykle rozbije, a každé z nich má vlastní odpověď.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="nástroje-artifacts-handler">Nástroje: Artifacts Handler<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#n%C3%A1stroje-artifacts-handler" class="hash-link" aria-label="Přímý odkaz na Nástroje: Artifacts Handler" title="Přímý odkaz na Nástroje: Artifacts Handler" translate="no">​</a></h2>
<p>„Nainstalujte GCC 13.2 a Ninja 1.12“ v README je věta, kterou nikdo nedodržuje doslova. Platforma to řeší tím, že z nástrojů dělá součást projektu. Artifacts Handler je skript CMake, který ze souboru <code>ArtifactsConfig.txt</code> přečte seznam nástrojů a jejich verzí a připraví je. Jeho dokumentace uvádí, že jediný software, který uživatel potřebuje, je Git a CMake, a že každou další komponentu buildu dodá handler. Po krocích:</p>
<ol>
<li class=""><strong>Naklonuje</strong> kořenový repozitář artefaktů (bez submodulů, aby se ušetřil provoz).</li>
<li class=""><strong>Najde</strong> v něm artefakt (každý nástroj je submodul, názvy se porovnávají bez ohledu na velikost písmen).</li>
<li class=""><strong>Checkoutne</strong> požadovanou verzi (mělký klon, <code>--depth=1</code>). Vydání jsou označena tagem podle verze a operačního systému (<code>Win</code>, <code>Unix</code>, <code>DarwinARM</code>).</li>
<li class=""><strong>Nainstaluje</strong> ho: rozbalí archiv do složky cache.</li>
<li class=""><strong>Inicializuje</strong> ho: ve většině případů vloží složku nástroje na <em>začátek</em> <code>PATH</code>, takže nástroj projektu vyhraje nad jakýmkoli nástrojem nainstalovaným v systému.</li>
</ol>
<p>Konfigurace má jeden řádek na nástroj, <code>name;version;handler version</code>, například řádky z dokumentace platformy:</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>První číslo je verze samotného nástroje (<em>binárky</em>), druhé je verze skriptu handleru daného artefaktu (může se měnit nezávisle, například když se opraví způsob nastavení <code>PATH</code>). Cache má jednu složku na nástroj a verzi, takže několik verzí žije vedle sebe a projekt, který potřebuje starší, neruší projekt, který potřebuje novější.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="proč-ne-latest">Proč ne <code>latest</code><a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#pro%C4%8D-ne-latest" class="hash-link" aria-label="Přímý odkaz na proč-ne-latest" title="Přímý odkaz na proč-ne-latest" translate="no">​</a></h3>
<p>Handler také přijímá <code>latest</code> místo čísla. Je to pohodlné a rozbíjí to celou myšlenku. Spustil jsem handler s řádkem <code>ninja;latest;latest</code> a vypsal, na co to 5. října 2026 přeložil:</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>(Běh se zastavil při stahování vydání, protože moje prostředí nedosáhne na GitHub API, ale vyřešení proběhlo.) <code>latest</code> je <strong>pohyblivý cíl</strong>: dokumentace říká, že seznam verzí se stahuje jednou denně, takže stejný soubor dnes dá 1.13.2 a po dalším vydání něco jiného. Build, který je dnes správný, může být zítra jiný build a nic ve vašem repozitáři to neříká. Pravidlo je proto jednoduché: <strong><code>latest</code> je pro zkoušení nové verze a vydaný projekt připíná každé číslo.</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="další-nastavení-která-pomáhají">Další nastavení, která pomáhají<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#dal%C5%A1%C3%AD-nastaven%C3%AD-kter%C3%A1-pom%C3%A1haj%C3%AD" class="hash-link" aria-label="Přímý odkaz na Další nastavení, která pomáhají" title="Přímý odkaz na Další nastavení, která pomáhají" translate="no">​</a></h3>
<ul>
<li class=""><strong>Offline režim</strong> (<code>-DOFFLINE_MODE=true</code>): kontroluje se jen lokální cache a nic se nestahuje. Je to způsob, jak dokázat, že build nezávisí na síti, a způsob, jak stavět tam, kde síť není.</li>
<li class=""><strong>Umístění cache</strong> (<code>ARTIFACTS_HANDLER_CACHE_PATH</code>) a <strong>kořenového repozitáře</strong> (<code>ARTIFACTS_HANDLER_ROOT_REPO_URL</code>) lze nastavit v konfiguračním souboru, v prostředí nebo na příkazové řádce. Firma může provozovat vlastní zrcadlo artefaktů, takže build nezávisí ani na veřejném serveru.</li>
<li class=""><strong>Kontrolní součet.</strong> Každé vydání artefaktu je publikováno se souborem SHA-256 vedle archivu, takže poškozený nebo vyměněný soubor není tiše přijat.</li>
</ul>
<p>Nástroje jsou první polovina odpovědi. Druhá polovina je něco, co si můžete ověřit sami, pomocí příkazu níže.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="prostředí-experiment">Prostředí: experiment<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#prost%C5%99ed%C3%AD-experiment" class="hash-link" aria-label="Přímý odkaz na Prostředí: experiment" title="Přímý odkaz na Prostředí: experiment" translate="no">​</a></h2>
<p>Vzal jsem ukázkový projekt z článku o <a class="" href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware">CMake</a> a přidal soubor, který má většina firmware v nějaké podobě: <strong>informace o buildu</strong>. Ukládá čas buildu a cestu ke zdrojovému souboru, protože někdo kdysi chtěl v debuggeru vidět „kdy se to přeložilo“:</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>Pak jsem stejný zdroj přeložil dvakrát: ve dvou různých složkách (<code>a</code> a <code>b</code>), druhý o tři sekundy později. Příkaz <code>strings</code> použitý na obě binárky ukazuje, co je uvnitř:</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>a SHA-256 obou souborů <code>firmware.bin</code> se liší:</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>Dva buildy jednoho zdroje, dvě různé binárky. Čas je zřejmý, ale <strong>cesta</strong> je ta, na kterou lidé zapomínají: <code>__FILE__</code> (a také <code>assert()</code> a ladicí informace) zapisuje do programu plnou cestu k souboru a cesta je jiná na PC každého vývojáře a v každé úloze CI. Binárka přeložená v <code>/home/anna/project</code> a ta samá přeložená v <code>/builds/job-4711/project</code> jsou dva různé soubory.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tři-změny">Tři změny<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#t%C5%99i-zm%C4%9Bny" class="hash-link" aria-label="Přímý odkaz na Tři změny" title="Přímý odkaz na Tři změny" translate="no">​</a></h3>
<p><strong>1. Odstraňte hodiny.</strong> Makra <code>__DATE__</code> a <code>__TIME__</code> nemají místo ve firmware, který má být reprodukovatelný. Překladač to dokáže vynutit, takže je nikdo omylem nepřidá zpět:</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. Verze je vstup.</strong> Pokud chcete vědět, „co je to za firmware“, build dostane odpověď zvenku: verzi, tag nebo hash commitu, který build systém předá jako definici. Stejný zdroj má stejnou verzi, tedy stejné bajty:</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. Odstraňte cesty.</strong> Volba <code>-ffile-prefix-map=OLD=NEW</code> nahradí prefix každé cesty, kterou GCC vloží do výstupu (<code>__FILE__</code>, ladicí informace, aserce). Zdrojová složka projektu se nahradí tečkou:</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>S těmito třemi změnami dá stejná kontrola:</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><code>.bin</code> je identický, stejně jako <code>.elf</code>, v release (<code>-Os -g0</code>) i v debug buildu (<code>-Og -g3</code>), jehož ladicí informace jsou plné cest. Díky <code>-ffile-prefix-map</code> ukazuje <code>strings</code> binárky <code>./Application/BuildInfo.c</code> a verzi <code>1.2.3</code> a nic o PC, které ji přeložilo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="test-který-nezestárne">Test, který nezestárne<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#test-kter%C3%BD-nezest%C3%A1rne" class="hash-link" aria-label="Přímý odkaz na Test, který nezestárne" title="Přímý odkaz na Test, který nezestárne" translate="no">​</a></h2>
<p>Nestačí udělat build reprodukovatelným jednou, protože první <code>__TIME__</code>, který někdo přidá, ho zničí. Udělejte z něj proto <strong>test</strong>: přeložte zdroj dvakrát a porovnejte. Tohle je skript, kterým jsem získal čísla výše; zkopíruje projekt do dvou složek, přeloží oba s pauzou mezi nimi a porovná 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>Spouštěný v CI při každém mergi je strážcem. Použil jsem ho i na rozbitou verzi informací o buildu, abych si byl jistý, že umí selhat, a selhal (<code>NOT REPRODUCIBLE</code>, návratový kód 1, dva různé hashe). Test, který nikdy neselhal, je test, který neznáte.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-dalšího-reprodukovatelný-build-rozbíjí">Co dalšího reprodukovatelný build rozbíjí<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#co-dal%C5%A1%C3%ADho-reprodukovateln%C3%BD-build-rozb%C3%ADj%C3%AD" class="hash-link" aria-label="Přímý odkaz na Co dalšího reprodukovatelný build rozbíjí" title="Přímý odkaz na Co dalšího reprodukovatelný build rozbíjí" translate="no">​</a></h2>
<p>Otestoval jsem tři věci výše. Následující jsou další dobře známé zdroje potíží, které byste měli mít na paměti (v příkladu jsem je nepotřeboval, takže je jen jmenuji):</p>
<ul>
<li class=""><strong>Pořadí souborů</strong> pocházející z <code>file(GLOB ...)</code> nebo z výpisu adresáře. Zdroje by měly být vypsané explicitně, jako v souborech CMake modulů platformy.</li>
<li class=""><strong>Časové razítko v archivu</strong> (statická knihovna vytvořená <code>ar</code>). Moderní verze nástrojů mají deterministický režim, ale starý toolchain ho mít nemusí.</li>
<li class=""><strong>Generovaný kód.</strong> Mocky a runnery unit testů nebo linker script generovaný pro MCU se musí generovat stejně ze stejných vstupů. Pravidla jsou řazení a žádná časová razítka na výstupu.</li>
<li class=""><strong>Samotný překladač.</strong> Stejná verze stejného překladače ze dvou zdrojů (balíček distribuce a archiv výrobce) se může lišit v knihovnách, které linkuje. To je důvod, proč brát překladač z jednoho místa, což je smyslem artefaktů.</li>
<li class=""><strong>Build s jiným počtem vláken.</strong> Správný build systém dá stejný výsledek s <code>-j1</code> i <code>-j16</code> a test toho je levným doplňkem k tomu výše.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kontrolní-seznam">Kontrolní seznam<a href="https://embedbits.cz/cs/blog/reproducible-builds-embedded#kontroln%C3%AD-seznam" class="hash-link" aria-label="Přímý odkaz na Kontrolní seznam" title="Přímý odkaz na Kontrolní seznam" translate="no">​</a></h2>
<ol>
<li class="">Každý nástroj je v <code>ArtifactsConfig.txt</code> připnutý na přesnou verzi. Žádné <code>latest</code> ve vydání.</li>
<li class="">Submoduly (BSP, platforma) jsou připnuté commity a aktualizace je viditelný commit.</li>
<li class="">Nic ve firmware nezávisí na čase ani cestě: <code>-Werror=date-time</code>, <code>-ffile-prefix-map</code>.</li>
<li class="">Verze je parametr buildu, odvozený z tagu, a je uložená ve firmware.</li>
<li class="">CI staví dvakrát a porovnává. Čas od času také staví offline, z cache.</li>
<li class="">Dodaná binárka je uložena spolu se svým SHA-256 a tagem, takže otázka „je to stejný soubor“ má odpověď bez nového buildu.</li>
</ol>
<p>Odměnou je věta, kterou použijete do telefonu se zákazníkem: <em>„Přeložil jsem přesně váš firmware a chyba v něm (ne)je.“</em></p>]]></content:encoded>
            <category>Embedded</category>
            <category>CMake</category>
            <category>Architektura</category>
        </item>
        <item>
            <title><![CDATA[Návrh API periferie: osm rozhodnutí za modulem Gpio]]></title>
            <link>https://embedbits.cz/cs/blog/designing-peripheral-api-gpio</link>
            <guid>https://embedbits.cz/cs/blog/designing-peripheral-api-gpio</guid>
            <pubDate>Wed, 07 Oct 2026 10:00:00 GMT</pubDate>
            <description><![CDATA[GPIO je nejjednodušší periferie mikrokontroléru jak se pin jmenuje, co funkce vrací, kde žije polarita LED. Modul Gpio z MCAL v Embedbits BSP je skutečný příklad se skutečnými odpověďmi a projdu je jednu po druhé, včetně alternativ a ceny.]]></description>
            <content:encoded><![CDATA[<p>GPIO je nejjednodušší periferie mikrokontroléru: pin je high nebo low. Právě proto je dobrým tématem pro článek o <strong>návrhu rozhraní</strong>. Není tu žádná hardwarová složitost, za kterou by se dalo schovat, a každé rozhodnutí je volbou návrháře: jak se pin jmenuje, co funkce vrací, kde žije polarita LED. Modul <code>Gpio</code> z MCAL v Embedbits BSP je skutečný příklad se skutečnými odpověďmi a projdu je jednu po druhé, včetně alternativ a ceny.</p>
<p>Kód z modulu je citován z větve STM32H5 repozitáře <a href="https://github.com/Embedbits/Bsp-Mcal-Gpio" target="_blank" rel="noopener noreferrer" class="">Bsp-Mcal-Gpio</a>. Příklady, které ho používají, byly přeloženy a spuštěny proti <strong>skutečným</strong> <code>Gpio_Port.h</code> a <code>Gpio_Types.h</code>, s malou náhradní implementací, aby bylo možné API vyzkoušet na PC.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="celé-rozhraní-na-jedné-obrazovce">Celé rozhraní na jedné obrazovce<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#cel%C3%A9-rozhran%C3%AD-na-jedn%C3%A9-obrazovce" class="hash-link" aria-label="Přímý odkaz na Celé rozhraní na jedné obrazovce" title="Přímý odkaz na Celé rozhraní na jedné obrazovce" 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>Každé rozhodnutí níže se dá vyčíst z tohoto seznamu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-pin-je-dvojice-identifikátorů-ne-makro-od-výrobce">1. Pin je dvojice identifikátorů, ne makro od výrobce<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#1-pin-je-dvojice-identifik%C3%A1tor%C5%AF-ne-makro-od-v%C3%BDrobce" class="hash-link" aria-label="Přímý odkaz na 1. Pin je dvojice identifikátorů, ne makro od výrobce" title="Přímý odkaz na 1. Pin je dvojice identifikátorů, ne makro od výrobce" translate="no">​</a></h2>
<p>Ovladače výrobce adresují pin ukazatelem na blok registrů a bitovou maskou: <code>LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5)</code>. MCAL místo toho bere dva výčtové typy, <code>gpio_PortId_t</code> a <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>Proč:</strong> kód nad MCAL nepotřebuje žádnou hlavičku výrobce, neví, co je <code>GPIOA</code> (adresa bloku registrů výrobce), a identifikátor lze kontrolovat na rozsah, což u libovolného ukazatele nejde. Každý výčet končí čítačem (<code>GPIO_PORT_CNT</code>, <code>GPIO_PIN_ID_CNT</code>), který je horní mezí pro kontrolu na začátku funkce.</p>
<p><strong>Cena:</strong> tabulka, která překládá identifikátor na blok registrů (v <code>Gpio.c</code>, jeden řádek na port), a jedna nepřímost navíc. Tabulka také řeší vlastní problém: MCU jedné rodiny mají různý počet portů, takže jsou položky obaleny v <code>#if defined(GPIOK)</code> (viz článek o <a class="" href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches">rodinách</a>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-každá-funkce-která-může-selhat-vrací-stav-a-výsledky-vycházejí-přes-ukazatel">2. Každá funkce, která může selhat, vrací stav, a výsledky vycházejí přes ukazatel<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#2-ka%C5%BEd%C3%A1-funkce-kter%C3%A1-m%C5%AF%C5%BEe-selhat-vrac%C3%AD-stav-a-v%C3%BDsledky-vych%C3%A1zej%C3%AD-p%C5%99es-ukazatel" class="hash-link" aria-label="Přímý odkaz na 2. Každá funkce, která může selhat, vrací stav, a výsledky vycházejí přes ukazatel" title="Přímý odkaz na 2. Každá funkce, která může selhat, vrací stav, a výsledky vycházejí přes ukazatel" translate="no">​</a></h2>
<p>Všechny funkce kromě <code>Deinit</code>, <code>Task</code> a getteru verze vracejí <code>gpio_RequestState_t</code> a gettery předávají hodnotu přes parametr typu ukazatel:</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>Proč:</strong> návratová hodnota getteru nemůže nést hodnotu <em>a zároveň</em> informaci, že hodnota není platná (<code>GPIO_PIN_LEVEL_LOW</code> je platná úroveň, takže vrácená <code>0</code> je nejednoznačná). Se stavem v návratové hodnotě a daty v parametru je neplatný port, neplatný pin nebo ukazatel <code>NULL</code> viditelnou chybou, a ne tiše špatnou úrovní. <code>* const</code> v signatuře říká, že funkce nemění ukazatel, jen data za ním.</p>
<p><strong>Cena:</strong> dva řádky místo jednoho při každém použití. A stav má dvě hodnoty (<code>GPIO_REQUEST_OK</code>, <code>GPIO_REQUEST_ERROR</code>), takže volající ví, <em>že</em> to selhalo, ale ne <em>proč</em>. Pro GPIO to stačí, protože důvodů je jen několik (neplatný identifikátor, <code>NULL</code>) a všechny jsou programátorské chyby. U periferie se skutečným selháním (timeout I2C, chyba sběrnice) volající potřebuje víc a obvyklou odpovědí je bohatší výčet.</p>
<p>Pravidlo z článku o <a class="" href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice">MISRA</a>, které tu platí, je 17.7 (vrácená hodnota se používá): rozhraní zde usnadňuje jeho dodržení, protože každá funkce, která může selhat, to říká hodnotou, na kterou se musíte podívat.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-pin-se-konfiguruje-daty-ne-posloupností-volání">3. Pin se konfiguruje daty, ne posloupností volání<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#3-pin-se-konfiguruje-daty-ne-posloupnost%C3%AD-vol%C3%A1n%C3%AD" class="hash-link" aria-label="Přímý odkaz na 3. Pin se konfiguruje daty, ne posloupností volání" title="Přímý odkaz na 3. Pin se konfiguruje daty, ne posloupností volání" translate="no">​</a></h2>
<p>Existuje konfigurační struktura se vším, co pin popisuje, a jedna funkce, která ji aplikuje:</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>Proč:</strong> znalost o desce pak žije v <strong>tabulce</strong> a kód, který ji aplikuje, je pro každou desku stejný. Podívejte se na příklad, který jsem přeložil a spustil: deska jsou dvě položky a inicializace je smyčka.</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>Protože je tabulka data, nová revize DPS změní řádek v tabulce a nic v kódu. V architektuře Embedbits je to úkol vrstvy HAL: drží tabulky a pomocí MCAL je aplikuje.</p>
<p><strong>Cena:</strong> struktura má osm polí a každá položka musí vyplnit všechna (designated initializers to činí čitelným a vynechané pole je nula, což není vždy rozumná hodnota). Proto je užitečným společníkem funkce <code>Get_DefaultConfig</code>, kterou mají některé jiné moduly.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-polarita-signálu-je-vlastnost-pinu-ne-kódu">4. Polarita signálu je vlastnost pinu, ne kódu<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#4-polarita-sign%C3%A1lu-je-vlastnost-pinu-ne-k%C3%B3du" class="hash-link" aria-label="Přímý odkaz na 4. Polarita signálu je vlastnost pinu, ne kódu" title="Přímý odkaz na 4. Polarita signálu je vlastnost pinu, ne kódu" translate="no">​</a></h2>
<p>Struktura má pole <code>PinActiveLevel</code> a existují funkce <code>Gpio_Set_PinStateActive()</code> a <code>Gpio_Set_PinStateInactive()</code>, které berou polaritu jako parametr. Důvodem je prostý fakt z elektroniky: LED může být připojena na zem (svítí s úrovní <strong>high</strong>) nebo na napájení (svítí s úrovní <strong>low</strong>) a signál chip-select bývá obvykle <em>active low</em>. Pokud kód říká <code>Gpio_Set_PinLevel(..., HIGH)</code> pro „LED zapnout“, je to správně pro jednu desku a špatně pro další.</p>
<p>S polaritou v tabulce aplikace řekne „zapnout“ a tabulka řekne, co to znamená. Ve výše uvedeném příkladu je LED připojena na napájení, takže <code>PinActiveLevel</code> je <code>GPIO_PIN_LEVEL_LOW</code> a test potvrzuje, co pin dělá:</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-výčty-jsou-konstanty-výrobce">5. Výčty jsou konstanty výrobce<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#5-v%C3%BD%C4%8Dty-jsou-konstanty-v%C3%BDrobce" class="hash-link" aria-label="Přímý odkaz na 5. Výčty jsou konstanty výrobce" title="Přímý odkaz na 5. Výčty jsou konstanty výrobce" translate="no">​</a></h2>
<p>Typy nevymýšlejí vlastní čísla, jsou to čísla ovladače výrobce:</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>Proč:</strong> převod z typu MCAL na hodnotu, kterou chce funkce LL, je <strong>zdarma</strong>: žádný <code>switch</code>, žádná tabulka a žádná možnost udělat v překladu překlep. Hodnoty konstant se mezi rodinami liší a to je skryto v jediném <code>#include</code> portu RAL (<code>Stm32_gpio.h</code> specifický pro rodinu).</p>
<p><strong>Cena:</strong> <code>Gpio_Types.h</code>, veřejná hlavička, zahrnuje hlavičku RAL, takže konstanty výrobce prosakují do hlaviček, které uživatelé modulu vidí. Alternativou je typ s vlastními hodnotami a překladová tabulka v souboru <code>.c</code>, což stojí kód a místo pro chybu, ale udrží výrobce mimo veřejné hlavičky. Rozhodnutí je kompromis a je dobré vědět, že jím je.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-stejný-životní-cyklus-jako-každý-jiný-modul">6. Stejný životní cyklus jako každý jiný modul<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#6-stejn%C3%BD-%C5%BEivotn%C3%AD-cyklus-jako-ka%C5%BEd%C3%BD-jin%C3%BD-modul" class="hash-link" aria-label="Přímý odkaz na 6. Stejný životní cyklus jako každý jiný modul" title="Přímý odkaz na 6. Stejný životní cyklus jako každý jiný modul" translate="no">​</a></h2>
<p><code>Gpio_Get_ModuleVersion()</code>, <code>Gpio_Init()</code>, <code>Gpio_Deinit()</code> a <code>Gpio_Task()</code> pocházejí ze šablony, kterou začíná každý modul (viz článek o <a class="" href="https://embedbits.cz/cs/blog/file-organization-embedded-c">organizaci souborů</a>). Rozdíl je na jednom místě, kde to dává smysl: <code>Gpio_Init()</code> není <code>void</code>, bere <strong>konfiguraci pinu</strong>. Modul GPIO nezná desku, takže „inicializovat modul“ nemá bez otázky „který pin?“ význam. Jednotný životní cyklus, který se ohne tam, kde to vyžaduje povaha modulu, je lepší než životní cyklus vnucený modulu, kam nepasuje.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-pořadí-kroků-je-součástí-rozhraní">7. Pořadí kroků je součástí rozhraní<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#7-po%C5%99ad%C3%AD-krok%C5%AF-je-sou%C4%8D%C3%A1st%C3%AD-rozhran%C3%AD" class="hash-link" aria-label="Přímý odkaz na 7. Pořadí kroků je součástí rozhraní" title="Přímý odkaz na 7. Pořadí kroků je součástí rozhraní" translate="no">​</a></h2>
<p>Podívejte se na komentář k <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>Režim pinu, tedy krok, který skutečně <strong>připojí výstupní budič k pádu</strong>, je poslední. Kdyby byl režim první, pin by na okamžik budil úroveň, kterou měl výstupní registr po resetu (obvykle low), a pak by skočil na správnou: puls na lince, která může být chip-select, reset jiného čipu nebo gate tranzistoru. Takový glitch není v debuggeru vidět, ale na osciloskopu ano. Je to dobrý příklad pravidla pro návrh API: <strong>když na pořadí kroků záleží hardwaru, má pořadí vlastnit funkce, která je provádí</strong>, aby ho uživatel nemohl pokazit.</p>
<p>Druhá věta komentáře, „stops at the first failed step“, je také návrhové rozhodnutí: funkce se nepokouší pokračovat po chybě a vrací stav selhavšího kroku.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="8-špatný-argument-je-chyba-kterou-volající-vidí-ne-pád">8. Špatný argument je chyba, kterou volající vidí, ne pád<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#8-%C5%A1patn%C3%BD-argument-je-chyba-kterou-volaj%C3%ADc%C3%AD-vid%C3%AD-ne-p%C3%A1d" class="hash-link" aria-label="Přímý odkaz na 8. Špatný argument je chyba, kterou volající vidí, ne pád" title="Přímý odkaz na 8. Špatný argument je chyba, kterou volající vidí, ne pád" translate="no">​</a></h2>
<p>Funkce kontrolují své argumenty a odpovědí je stav:</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>(Je to test mé náhradní implementace, ale skutečný <code>Gpio_Init()</code> dělá totéž pro <code>NULL</code>: celé tělo je uvnitř <code>if( GPIO_NULL_PTR != gpioConfig )</code>.) Konstanty <code>_CNT</code> mají zde druhý úkol: <code>GPIO_PORT_CNT</code> je první hodnota, která <strong>není</strong> platným portem, takže kontrola je jediné porovnání. Ve firmware není komu ukázat zprávu a <code>assert</code>, který zastaví program, je pro produkční build obvykle špatná odpověď. Lepší je chyba, která jde nahoru k volajícímu, jenž ví, co dělat (a k modulu nad MCAL, který ví, co je kritické).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="na-co-bych-se-podíval-znovu">Na co bych se podíval znovu<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#na-co-bych-se-pod%C3%ADval-znovu" class="hash-link" aria-label="Přímý odkaz na Na co bych se podíval znovu" title="Přímý odkaz na Na co bych se podíval znovu" translate="no">​</a></h2>
<p>Poctivé review návrhu má vždy seznam a tento má dvě položky, které pocházejí z článku o MISRA:</p>
<ul>
<li class=""><code>Gpio_Init( gpio_Config_t *gpioConfig )</code> strukturu jen <strong>čte</strong>, takže parametr by mohl být <code>const gpio_Config_t *</code> (Rule 8.13). Signatura by říkala, že funkce konfiguraci nemění, a tabulka desky by mohla být <code>const</code> a žít ve flash místo v RAM.</li>
<li class="">Dvouhodnotový <code>gpio_RequestState_t</code> je ve všech modulech stejný (generuje ho šablona). Je to jednoduché a jednotné rozhodnutí, které je pro GPIO správné, a moduly se skutečnými selháními budou dříve či později potřebovat víc.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="principy-ve-zkratce">Principy ve zkratce<a href="https://embedbits.cz/cs/blog/designing-peripheral-api-gpio#principy-ve-zkratce" class="hash-link" aria-label="Přímý odkaz na Principy ve zkratce" title="Přímý odkaz na Principy ve zkratce" translate="no">​</a></h2>
<ol>
<li class=""><strong>Skrývejte hardware, ne záměr.</strong> Uživatel říká <em>který pin</em> a <em>jaká polarita</em>, ne <em>který registr</em>.</li>
<li class=""><strong>Dělejte neplatný stav viditelným.</strong> Status pro všechno, co může selhat, a výstup jen při úspěchu.</li>
<li class=""><strong>Dejte znalost do dat.</strong> Deska je tabulka, kterou čte smyčka.</li>
<li class=""><strong>Nechte funkci vlastnit pořadí,</strong> když na něm hardwaru záleží.</li>
<li class=""><strong>Udržujte rozhraní stejné a říkejte poctivě, kde je ohnuté</strong> (<code>Init</code> s parametrem) <strong>a kde abstrakce prosakuje</strong> (konstanty výrobce v typech).</li>
</ol>
<p>Rozhraní má dva čtenáře: uživatele dneška a správce příštího roku. Rozhodnutí výše jsou psána pro oba a komentáře v hlavičkách jsou důkazem, že někdo myslel na toho druhého.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>Architektura</category>
        </item>
        <item>
            <title><![CDATA[Doxygen pro embedded C: dokumentace, na kterou nelze zapomenout]]></title>
            <link>https://embedbits.cz/cs/blog/doxygen-embedded-c</link>
            <guid>https://embedbits.cz/cs/blog/doxygen-embedded-c</guid>
            <pubDate>Tue, 06 Oct 2026 20:00:00 GMT</pubDate>
            <description><![CDATA[Každý projekt má dokumentaci a každý projekt má dokumentaci, která lže. Word soubor s popisem rozhraní byl správný v týdnu, kdy vznikl. Komentář nad funkcí je poctivější, protože je pár řádků od kódu, který popisuje, ale píší ho tytéž lidé, kteří zapomínají. Cesta ven nevede přes větší disciplínu, ale přes nástroj, který komentáře přečte, sestaví z nich dokumentaci a shodí build, když něco chybí. Tím nástrojem je Doxygen.]]></description>
            <content:encoded><![CDATA[<p>Každý projekt má dokumentaci a každý projekt má dokumentaci, která lže. Word soubor s popisem rozhraní byl správný v týdnu, kdy vznikl. Komentář nad funkcí je poctivější, protože je pár řádků od kódu, který popisuje, ale píší ho tytéž lidé, kteří zapomínají. Cesta ven nevede přes větší disciplínu, ale přes <strong>nástroj, který komentáře přečte, sestaví z nich dokumentaci a shodí build, když něco chybí</strong>. Tím nástrojem je Doxygen.</p>
<p>Tento článek ukazuje, jak vypadá zdokumentovaný modul v mých projektech, jak se generuje a jak z dokumentace udělat součást CI, kterou nelze přeskočit. Příklady vznikly s Doxygen 1.9.8 a Graphviz a výstupy jsou skutečné.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-dokumentovat-a-co-ne">Co dokumentovat a co ne<a href="https://embedbits.cz/cs/blog/doxygen-embedded-c#co-dokumentovat-a-co-ne" class="hash-link" aria-label="Přímý odkaz na Co dokumentovat a co ne" title="Přímý odkaz na Co dokumentovat a co ne" translate="no">​</a></h2>
<p>Můj <a class="" href="https://embedbits.cz/cs/docs/platform/embi-platform/coding-style">coding style</a> o tom má jeden odstavec: komentáře ve stylu Doxygen pro všechny <strong>veřejné</strong> funkce, typy a makra, v angličtině, krátké a přesné, <em>proč</em> a ne <em>co</em>. Pár příkladů rozdílu:</p>





















<table><thead><tr><th>Komentář, který nic nestojí</th><th>Komentář, který pomáhá</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>První sloupec opakuje název funkce, který čtenář už vidí. Druhý sloupec říká to, co čtenář <strong>vidět nemůže</strong>: jednotku, platný rozsah, kdo vlastní paměť, zda se výstup zapisuje v případě chyby, odkud lze funkci volat, co je třeba udělat předtím. Pro embedded rozhraní je to také místo pro informace, které je nebezpečné hádat: <em>je bezpečné volat to z přerušení</em>, <em>jak dlouho může blokovat</em>, <em>smí být ukazatel NULL</em>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="modul-v-souborech-platformy">Modul v souborech platformy<a href="https://embedbits.cz/cs/blog/doxygen-embedded-c#modul-v-souborech-platformy" class="hash-link" aria-label="Přímý odkaz na Modul v souborech platformy" title="Přímý odkaz na Modul v souborech platformy" translate="no">​</a></h2>
<p>Šablony EmBi_Platform, z nichž každý modul začíná, mají stejnou dokumentační kostru: hlavičku souboru s <code>\author</code>, <code>\file</code>, <code>\ingroup</code> a <code>\brief</code> a nad každou funkcí blok s <code>\brief</code>, popisem a <code>\return</code>. Šablona konečného automatu přidává <code>\pre</code> pro předpoklady a blok <code>\par Used global variables</code> se seznamem proměnných, které funkce čte (<code>in</code>), zapisuje (<code>out</code>) nebo obojí (<code>in,out</code>), což je překvapivě užitečný druh dokumentace: tok dat funkce na třech řádcích.</p>
<p>Celý modul je v Doxygenu jedna <strong>skupina</strong>. <code>\ingroup Temperature</code> v každém souboru říká, že soubor patří k modulu, a samotná skupina se definuje jednou, v port souboru:</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>Typy mají krátký popis typu a každé hodnoty (komentář <code>/**&lt; ... */</code> za členem dokumentuje člen na stejném řádku):</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="generování">Generování<a href="https://embedbits.cz/cs/blog/doxygen-embedded-c#generov%C3%A1n%C3%AD" class="hash-link" aria-label="Přímý odkaz na Generování" title="Přímý odkaz na Generování" translate="no">​</a></h2>
<p>Doxygen se konfiguruje souborem s několika sty voleb. Psát ho ručně je chyba, které se snadno vyhnete: platforma má soubor jako šablonu (<code>Doxyfile.in</code> v artefaktu Doxygen) a plní ho z proměnných CMake a projekty nastavují jen ty, které se liší od výchozích. Totéž umožňuje modul samotného CMake a toto je celá konfigurace příkladu:</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>a build je jeden 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>Výsledkem je složka s HTML stránkami. Skupina modulu se soubory, které k ní patří, a popisem z port souboru vypadá takto:</p>
<p><img decoding="async" loading="lazy" alt="Stránka skupiny Temperature ve vygenerované HTML dokumentaci" src="https://embedbits.cz/cs/assets/images/doxygen-module-group-7e9b023f433e65035665cd32e2f490ba.png" width="1000" height="900" class="img_ev3q"></p>
<p>Doxygen také kreslí <strong>include graph</strong> každého souboru a <strong>call graph</strong> a <strong>caller graph</strong> každé zdokumentované funkce (<code>HAVE_DOT</code>, Graphviz: proto má platforma pro něj artefakt). Include grafy stojí za občasný pohled: šipka z aplikačního souboru do interní hlavičky modulu je tentýž problém, který popisuje <a class="" href="https://embedbits.cz/cs/blog/file-organization-embedded-c">článek o organizaci souborů</a>, jen viděný shora.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dokumentace-jako-test">Dokumentace jako test<a href="https://embedbits.cz/cs/blog/doxygen-embedded-c#dokumentace-jako-test" class="hash-link" aria-label="Přímý odkaz na Dokumentace jako test" title="Přímý odkaz na Dokumentace jako test" translate="no">​</a></h2>
<p>Tohle je část, která mění disciplínu. Čtyři volby změní chybějící dokumentaci z „měli bychom“ na „build je červený“:</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>S <code>FAIL_ON_WARNINGS</code> Doxygen projde vše, vypíše <strong>všechna</strong> varování a teprve potom skončí chybou (prosté <code>YES</code> se zastaví u prvního). Vyzkoušel jsem to: z port souboru jsem smazal popis <code>Temperature_Task()</code> a <code>\param</code> u <code>Temperature_Get_Value()</code> a build ohlásil:</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>(Návratový kód příkazu je 1, takže CI je červené.) Po vrácení popisů stejný build skončí bez jakéhokoli výstupu a s návratovým kódem 0. Nová funkce bez komentáře se tak už nemůže omylem dostat do hlavní větve a nikdo nemusí být tím, kdo si to při review pohlídá.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-obsahuje-dobrá-dokumentace-rozhraní">Co obsahuje dobrá dokumentace rozhraní<a href="https://embedbits.cz/cs/blog/doxygen-embedded-c#co-obsahuje-dobr%C3%A1-dokumentace-rozhran%C3%AD" class="hash-link" aria-label="Přímý odkaz na Co obsahuje dobrá dokumentace rozhraní" title="Přímý odkaz na Co obsahuje dobrá dokumentace rozhraní" translate="no">​</a></h2>
<p>U každé funkce veřejného rozhraní projděte seznam:</p>
<ol>
<li class=""><strong>Co dělá</strong>, jednou větou, se slovesem (<code>\brief</code>).</li>
<li class=""><strong>Parametry</strong>: směr (<code>[in]</code>, <code>[out]</code>, <code>[in,out]</code>), jednotka, rozsah, zda je povoleno <code>NULL</code>.</li>
<li class=""><strong>Návratová hodnota</strong>: každá hodnota, která může být vrácena, a co znamená.</li>
<li class=""><strong>Předpoklady</strong> (<code>\pre</code>): co je třeba udělat předtím, například inicializaci.</li>
<li class=""><strong>Kontext</strong>: lze funkci volat z přerušení, blokuje, jak dlouho trvá.</li>
<li class=""><strong>Vedlejší efekty</strong>: co dalšího mění (globální stav, periferii).</li>
</ol>
<p>Pokud funkce nemá odpověď na jednu z těchto otázek, odpověď je v kódu a čtenář si ji musí přečíst. To je znamení, že rozhraní není dokončené, a psaní komentáře je často okamžik, kdy to zjistíte.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kam-to-v-platformě-zapadá">Kam to v platformě zapadá<a href="https://embedbits.cz/cs/blog/doxygen-embedded-c#kam-to-v-platform%C4%9B-zapad%C3%A1" class="hash-link" aria-label="Přímý odkaz na Kam to v platformě zapadá" title="Přímý odkaz na Kam to v platformě zapadá" translate="no">​</a></h2>
<p>Každý modul platformy má ve svém <code>CMakeLists.txt</code> volání, které registruje jeho složku pro dokumentaci (když je v projektu dostupný artefakt Doxygen), a kořenový build má volbu <code>DOXYGEN_ENABLED</code>. Dokumentace celého firmwaru se tedy generuje stejným buildem jako firmware: <code>-DDOXYGEN_ENABLED=ON</code>. Artefakty (Doxygen a Graphviz) se stahují ve verzi, kterou má projekt připnutou, takže stránky z dneška a z příštího roku vypadají stejně.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kontrolní-seznam">Kontrolní seznam<a href="https://embedbits.cz/cs/blog/doxygen-embedded-c#kontroln%C3%AD-seznam" class="hash-link" aria-label="Přímý odkaz na Kontrolní seznam" title="Přímý odkaz na Kontrolní seznam" translate="no">​</a></h2>
<ol>
<li class="">Každá veřejná funkce, typ a makro má popis. Interní jen tam, kde to není zřejmé.</li>
<li class="">Popis říká to, co čtenář nevidí v signatuře: jednotky, rozsahy, kontext, chyby.</li>
<li class="">Jedna skupina na modul (<code>\defgroup</code> v port souboru, <code>\ingroup</code> v ostatních).</li>
<li class=""><code>WARN_IF_UNDOCUMENTED</code>, <code>WARN_NO_PARAMDOC</code> a <code>FAIL_ON_WARNINGS</code> v CI.</li>
<li class="">Grafy jsou zapnuté a někdo se čas od času podívá na include graph aplikace.</li>
<li class="">Dokumentace se generuje ze stejného buildu jako firmware, s připnutými nástroji.</li>
</ol>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>CMake</category>
        </item>
        <item>
            <title><![CDATA[CMake pro embedded firmware: build, který se dá číst]]></title>
            <link>https://embedbits.cz/cs/blog/cmake-for-embedded-firmware</link>
            <guid>https://embedbits.cz/cs/blog/cmake-for-embedded-firmware</guid>
            <pubDate>Tue, 06 Oct 2026 18:00:00 GMT</pubDate>
            <description><![CDATA[Projekt v IDE je soubor, který nikdo nečte build je text, který čtete, revidujete, verzujete a spouštíte v CI úplně stejně jako u svého stolu.]]></description>
            <content:encoded><![CDATA[<p>Projekt v IDE je soubor, který nikdo nečte: několik tisíc řádků XML, které IDE zapíše a IDE přečte a které nelze zrevidovat v pull requestu. Build pak existuje jen na počítači, kde ho někdo naklikal. CMake to řeší jinou filozofií: <strong>build je text, který čtete, revidujete, verzujete a spouštíte v CI</strong> úplně stejně jako u svého stolu.</p>
<p>Build systém platformy Embedbits (EmBi_Platform) je postaven na CMake a tento článek vysvětluje části, které potřebuje každý embedded build v CMake, na malém projektu, který jsem sestavil a spustil: toolchain file, pojmenované flagy, typy buildu, moduly jako knihovny, linker script, soubory po linkování a test, který spouští firmware v simulátoru. Všechna čísla a výstupy jsou skutečné.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dvě-vrstvy-projekt-a-platforma">Dvě vrstvy: projekt a platforma<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#dv%C4%9B-vrstvy-projekt-a-platforma" class="hash-link" aria-label="Přímý odkaz na Dvě vrstvy: projekt a platforma" title="Přímý odkaz na Dvě vrstvy: projekt a platforma" translate="no">​</a></h2>
<p>Platforma dělí build na dvě části a tento nápad stojí za okopírování i pro malý projekt. Kořenový <code>CMakeLists.txt</code> produktu je minimální vstupní bod a vše složité žije v samostatném skriptu, který je <strong>verzovaný a sdílený</strong> (Git submodul) a který kořen vkládá:</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>Skript platformy zná typy buildu (<code>Debug</code>, <code>Release</code>, <code>UnitTest</code>, <code>IntegrationTest</code>), kontroly parametrů, toolchain, include cesty a registraci modulů. Produkt doplní jen to, co je pro něj specifické. Oprava buildu je pak nová verze submodulu a ne úprava deseti produktů. Příklad níže má obě části v jednom projektu, aby byl krátký, ale zachovává stejné oddělení: <code>cmake/</code> je „platforma“ a <code>CMakeLists.txt</code> je „produkt“.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ukázkový-projekt">Ukázkový projekt<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#uk%C3%A1zkov%C3%BD-projekt" class="hash-link" aria-label="Přímý odkaz na Ukázkový projekt" title="Přímý odkaz na Ukázkový projekt" 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="toolchain-file-kompilátor-není-pc">Toolchain file: kompilátor není PC<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#toolchain-file-kompil%C3%A1tor-nen%C3%AD-pc" class="hash-link" aria-label="Přímý odkaz na Toolchain file: kompilátor není PC" title="Přímý odkaz na Toolchain file: kompilátor není PC" translate="no">​</a></h2>
<p>CMake předpokládá, že sestavujete pro počítač, u kterého sedíte. Toolchain file říká něco jiného:</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>Řádek, na který lidé zapomínají, je <code>CMAKE_TRY_COMPILE_TARGET_TYPE</code>. CMake na začátku sestaví testovací program, aby ověřil, že kompilátor funguje, a bare-metal kompilátor nedokáže slinkovat program pro PC (neexistuje operační systém ani <code>main</code>, který by někdo volal). Když je cílem kontroly statická knihovna, test projde. Toolchain se zadává na příkazové řádce, jednou, při vytvoření složky buildu:</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>Stejná složka se zdrojáky s jiným <code>-B</code> je jiný build: vedle ní <code>build-release</code> nebo build pro unit testy na PC, bez toolchain file.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pojmenované-flagy">Pojmenované flagy<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#pojmenovan%C3%A9-flagy" class="hash-link" aria-label="Přímý odkaz na Pojmenované flagy" title="Přímý odkaz na Pojmenované flagy" translate="no">​</a></h2>
<p>Řádek jako <code>-mcpu=cortex-m4 -mthumb -mfloat-abi=soft -ffunction-sections ...</code> se špatně revidují, protože nikdo neví, která jeho část je důležitá. Platforma má soubor <code>Flags.cmake</code> s proměnnou pro každý flag a s komentářem (<code>THUMB_MODE</code>, <code>ENABLE_ALL_WARNINGS</code>, <code>REMOVE_UNUSED_FUNCTIONS</code>, <code>ENABLE_GC_SECTIONS</code>, <code>PRINT_MEMORY_USAGE</code> a tak dále, plus varianty CPU a FPU od Cortex-M0 po M85). Projekt se pak čte jako věta. Ten můj má jen to, co příklad potřebuje:</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="cmakeliststxt">CMakeLists.txt<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#cmakeliststxt" class="hash-link" aria-label="Přímý odkaz na CMakeLists.txt" title="Přímý odkaz na CMakeLists.txt" translate="no">​</a></h2>
<p>Celý kořenový soubor příkladu, 80 řádků:</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>Vysvětlím několik řádků, které rozhodují o tom, zda bude firmware správný.</p>
<p><strong>Typy buildu s explicitními flagy.</strong> Jsou jen dva, <code>Debug</code> (<code>-Og -g3</code>: dost rychlý a laditelný) a <code>Release</code> (<code>-Os -g0</code>: malý a bez ladicích informací) a cokoli jiného zastaví konfiguraci chybovou hláškou. Platforma má další dva, <code>UnitTest</code> a <code>IntegrationTest</code>: u prvního se <code>TARGET_MCU</code> ani nepotřebuje, protože se sestavuje pro PC.</p>
<p><strong>Výchozí flagy CMake.</strong> To je past. CMake přidává ke každé konfiguraci vlastní flagy, <code>-O3 -DNDEBUG</code> pro <code>Release</code> a <code>-g</code> pro <code>Debug</code>, a to před vaše vlastní. V první verzi příkladu vypadal příkaz kompilace pro release takto:</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>Vyhrává poslední <code>-O</code>, takže to bylo <code>-Os</code>, ale <code>-DNDEBUG</code> (které vypíná <code>assert()</code>) tam bylo, i když jsem o ně nikdy nežádal. Pokud chcete vědět, co sestavujete, vymažte výchozí hodnoty (<code>set(CMAKE_C_FLAGS_RELEASE "")</code>) a vše napište do vlastního souboru. Jak zjistit, co se skutečně předává kompilátoru, ukazuje <code>compile_commands.json</code>, který vytvoří volba <code>CMAKE_EXPORT_COMPILE_COMMANDS</code>: je to také soubor, který čtou editory a <code>clang-tidy</code>.</p>
<p><strong>Startup kód je knihovna typu <code>OBJECT</code>.</strong> Objekty takové knihovny se vkládají přímo do spustitelného souboru, bez spoléhání na to, že je linker vytáhne z archivu.</p>
<p><strong>Linker script je závislost</strong> (<code>LINK_DEPENDS</code>): když se změní, firmware se slinkuje znovu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="moduly-jsou-knihovny">Moduly jsou knihovny<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#moduly-jsou-knihovny" class="hash-link" aria-label="Přímý odkaz na Moduly jsou knihovny" title="Přímý odkaz na Moduly jsou knihovny" translate="no">​</a></h2>
<p>Každý modul je statická knihovna se seznamem <strong>vlastních</strong> zdrojových souborů a veřejných hlaviček (<a class="" href="https://embedbits.cz/cs/blog/file-organization-embedded-c">článek o organizaci souborů</a> vysvětluje proč). Aplikace knihovnu linkuje a získá s ní include cestu k veřejným hlavičkám a nic víc. V souboru CMake modulu není žádné <code>file(GLOB ...)</code>: zdrojové soubory jsou vyjmenovány jeden po druhém, takže nový soubor je viditelná změna v pull requestu a soubor, který ve složce omylem zůstal, se do firmwaru nedostane.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="target_mcu-jedno-jméno-několik-definic"><code>TARGET_MCU</code>: jedno jméno, několik definic<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#target_mcu-jedno-jm%C3%A9no-n%C4%9Bkolik-definic" class="hash-link" aria-label="Přímý odkaz na target_mcu-jedno-jméno-několik-definic" title="Přímý odkaz na target_mcu-jedno-jméno-několik-definic" translate="no">​</a></h2>
<p>Buildy platformy se spouštějí s <code>-DTARGET_MCU=STM32G474xE</code>. Skript jméno rozebere regulárním výrazem a z jednoho parametru vytvoří definice pro kód (<code>STM32G474xx</code> a <code>STM32G4xx</code>), které hlavičky výrobce používají k výběru správného zařízení. Stejná logika, spuštěná na čtyřech jménech:</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>To je odkaz na článek o <a class="" href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches">rodinách STM32 a větvích</a>: rodina rozhoduje, která větev BSP je ve stromu, a jméno MCU rozhoduje o definicích a linker scriptu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-vám-řekne-linker">Co vám řekne linker<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#co-v%C3%A1m-%C5%99ekne-linker" class="hash-link" aria-label="Přímý odkaz na Co vám řekne linker" title="Přímý odkaz na Co vám řekne linker" translate="no">​</a></h2>
<p><code>-Wl,--print-memory-usage</code> na konci každého linkování vypíše, kolik z každé paměti je využito, <code>-Wl,-Map=firmware.map</code> zapíše adresu všeho a post-build krok vypíše velikost:</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>Dva experimenty, které jsem s těmito čísly provedl, ukazují, proč jsou flagy v buildu a ne v něčí hlavě.</p>
<p><strong>Linker umí zahodit to, co nikdo nevolá.</strong> S <code>-ffunction-sections -fdata-sections</code> je každá funkce ve vlastní sekci a <code>-Wl,--gc-sections</code> dovolí linkeru odstranit ty, na které nikdo neodkazuje. Příklad obsahuje funkci <code>Unused_Checksum()</code>, kterou nikdo nevolá:</p>

















<table><thead><tr><th>Build</th><th>Velikost kódu</th></tr></thead><tbody><tr><td>Release, bez flagů sekcí a bez <code>--gc-sections</code></td><td>324 B</td></tr><tr><td>Release, s nimi (<code>-DGC_SECTIONS=ON</code>)</td><td><strong>276 B</strong></td></tr></tbody></table>
<p>Rozdíl 48 bajtů je přesně funkce checksum. V reálném projektu s knihovnou výrobce, která má stovky funkcí, z nichž voláte deset, jsou rozdíly v kilobajtech.</p>
<p><strong>Kompilátor umí přidat paměť za vašimi zády.</strong> První release build příkladu měl <strong>772 B</strong>, téměř třikrát víc než debug build (288 B). Map soubor ukázal <code>memcpy</code> a <code>memset</code> ze standardní knihovny. Příčina: při zapnuté optimalizaci GCC rozpozná smyčky ve startup kódu (kopírování <code>.data</code> a nulování <code>.bss</code>) jako kopii a výplň a nahradí je voláním těchto dvou funkcí, které pak přinesou svůj kód z knihovny. Jeden flag na startup objektu to opraví a výsledek je <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>Kromě velikosti je tu druhý důvod, proč na tom záleží: startup kód běží <em>před</em> inicializací paměti a čím méně knihovního kódu používá, tím méně se může pokazit (viz článek o tom, <a class="" href="https://embedbits.cz/cs/blog/before-main-startup-linker">co se děje před <code>main()</code></a>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="po-linkování-co-nahrajete-a-co-otestujete">Po linkování: co nahrajete a co otestujete<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#po-linkov%C3%A1n%C3%AD-co-nahrajete-a-co-otestujete" class="hash-link" aria-label="Přímý odkaz na Po linkování: co nahrajete a co otestujete" title="Přímý odkaz na Po linkování: co nahrajete a co otestujete" translate="no">​</a></h2>
<p>Příkaz <code>POST_BUILD</code> vytvoří z ELF souboru <code>firmware.bin</code> a <code>firmware.hex</code> (formáty, které čtou programátory) a vypíše velikost. Poslední částí příkladu je test: <code>add_test</code> spustí firmware v QEMU a <code>ctest</code> zkontroluje, že vypsal očekávaný 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>Je to <em>smoke test</em> (nastartuje firmware a dojde do svého <code>main()</code>?) a běží zlomek vteřiny při každém commitu. Nenahrazuje test na hardwaru, ale build, který nenastartuje, se najde v CI a ne u stolu. Testy modulů na PC jsou jiný build téhož projektu CMake (ukazuje ho <a class="" href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock">článek o Unity a CMock</a>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kontrolní-seznam">Kontrolní seznam<a href="https://embedbits.cz/cs/blog/cmake-for-embedded-firmware#kontroln%C3%AD-seznam" class="hash-link" aria-label="Přímý odkaz na Kontrolní seznam" title="Přímý odkaz na Kontrolní seznam" translate="no">​</a></h2>
<ol>
<li class="">Toolchain file a <code>CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY</code>.</li>
<li class="">Flagy v jednom souboru s názvy, výchozí hodnoty CMake pro konfigurace vymazané.</li>
<li class="">Každý modul je knihovna s explicitním seznamem zdrojů a veřejných hlaviček.</li>
<li class=""><code>-ffunction-sections -fdata-sections</code> a <code>--gc-sections</code>, vždy.</li>
<li class=""><code>--print-memory-usage</code> a map soubor při každém linkování, <code>size</code> po něm.</li>
<li class=""><code>compile_commands.json</code> pro editor a statickou analýzu.</li>
<li class="">Linker script je závislost firmwaru.</li>
<li class="">Smoke test v simulátoru v CI.</li>
<li class="">Čas od času se podívejte na velikost <em>release</em> buildu. Pokud roste bez důvodu, map soubor ví proč.</li>
</ol>]]></content:encoded>
            <category>Embedded</category>
            <category>CMake</category>
            <category>STM32</category>
        </item>
        <item>
            <title><![CDATA[Přerušení a main(): jak bezpečně sdílet data]]></title>
            <link>https://embedbits.cz/cs/blog/interrupts-and-main-shared-data</link>
            <guid>https://embedbits.cz/cs/blog/interrupts-and-main-shared-data</guid>
            <pubDate>Tue, 06 Oct 2026 14:00:00 GMT</pubDate>
            <description><![CDATA[Obsluha přerušení a hlavní smyčka jsou dva programy, které běží ve stejné paměti a o sobě nevědí. Překladač C neví, že přerušení existuje, a CPU neví, že dvě proměnné patří k sobě. Ví to jen programátor a chyby, které z toho vznikají, jsou ty nejhorší: objeví se jednou za tisíc běhů, zmizí, když připojíte debugger, a při code review se nikdy neukážou, protože kód vypadá správně.]]></description>
            <content:encoded><![CDATA[<p>Obsluha přerušení a hlavní smyčka jsou dva programy, které běží ve stejné paměti a o sobě nevědí. Překladač C neví, že přerušení existuje, a CPU neví, že dvě proměnné patří k sobě. Ví to jen programátor a chyby, které z toho vznikají, jsou ty nejhorší: objeví se jednou za tisíc běhů, zmizí, když připojíte debugger, a při code review se nikdy neukážou, protože kód vypadá správně.</p>
<p>Tento článek prochází tři problémy sdílených dat, jeden po druhém, s kódem, který <strong>selhává</strong>, a potom ukazuje vzory, které fungují. Experimenty běží na Cortex-M4 (v QEMU, na modelu desky s STM32F4) nebo na PC a výstupy jsou skutečné.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="problém-1-překladač-přerušení-nevidí">Problém 1: překladač přerušení nevidí<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#probl%C3%A9m-1-p%C5%99eklada%C4%8D-p%C5%99eru%C5%A1en%C3%AD-nevid%C3%AD" class="hash-link" aria-label="Přímý odkaz na Problém 1: překladač přerušení nevidí" title="Přímý odkaz na Problém 1: překladač přerušení nevidí" translate="no">​</a></h2>
<p>Nejjednodušší komunikace mezi přerušením a hlavní smyčkou je příznak (flag). Přerušení ho nastaví, hlavní smyčka na něj čeká:</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>To je celý program a s optimalizací <code>-O2</code> <strong>nikdy neskončí</strong>. Spustil jsem ho v QEMU s SysTick jako zdrojem přerušení (přerušení se spustí a nastaví příznak) a porovnal verzi s <code>volatile</code> a bez něj:</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>Proč? Podívejte se, co překladač vygeneroval pro smyčku v první verzi:</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>Překladač uvažuje jen o kódu <code>main()</code> a v tom kódu do <code>dataReady</code> nikdo nezapisuje. Hodnota se tedy nemůže změnit, stačí ji přečíst jednou a smyčka se stane nekonečnou. Přesně to, oč jste z jeho pohledu požádali. S <code>volatile</code> musí překladač číst proměnnou z paměti při každém průchodu:</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>Poučení: <strong>každá proměnná sdílená mezi přerušením a hlavním kódem musí být <code>volatile</code>.</strong> Totéž platí pro každý registr periferie, což je důvod, proč jsou definice registrů v hlavičkách CMSIS <code>volatile</code>. Mějte na paměti, že bez toho to v debug buildu (<code>-O0</code>) funguje a v release buildu selže, a proto se chyba najde pozdě.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="problém-2-volatile-nezaručuje-atomicitu">Problém 2: <code>volatile</code> nezaručuje atomicitu<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#probl%C3%A9m-2-volatile-nezaru%C4%8Duje-atomicitu" class="hash-link" aria-label="Přímý odkaz na problém-2-volatile-nezaručuje-atomicitu" title="Přímý odkaz na problém-2-volatile-nezaručuje-atomicitu" translate="no">​</a></h2>
<p><code>volatile</code> říká „čti a zapisuj paměť pokaždé“. Neříká „všechno najednou“. Nevinný řádek <code>counter++</code> jsou tři instrukce:</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>Pokud přerušení přijde mezi načtením a uložením a přerušení také inkrementuje čítač, jedna ze dvou inkrementací se <strong>ztratí</strong>: hlavní kód uloží starou hodnotu plus jedna přes hodnotu, kterou právě uložilo přerušení. Časová osa:</p>



































<table><thead><tr><th>Krok</th><th>Hlavní kód</th><th>Přerušení</th><th>Čítač</th></tr></thead><tbody><tr><td>1</td><td>načte 5</td><td></td><td>5</td></tr><tr><td>2</td><td></td><td>načte 5, přičte 1, uloží 6</td><td>6</td></tr><tr><td>3</td><td>přičte 1 (v registru má 5)</td><td></td><td>6</td></tr><tr><td>4</td><td>uloží 6</td><td></td><td><strong>6, mělo být 7</strong></td></tr></tbody></table>
<p>Chtěl jsem to ukázat i na Cortex-M4 a nevyšlo to: ve 200 000 inkrementacích s přerušením každých pár instrukcí QEMU nic neztratilo. Pravděpodobně proto, že QEMU kontroluje přerušení mezi bloky přeloženého kódu, takže žádné nikdy nepřistane mezi <code>ldr</code> a <code>str</code>. Je to užitečná připomínka, že <strong>simulátor neprokazuje nepřítomnost race condition</strong>: skutečné MCU může přerušit po každé instrukci. Stejný race, na místě, kde se snadno reprodukuje, jsou dvě vlákna na 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>Třetina všech inkrementací se ztratí a výsledky se běh od běhu liší. Vlákno na PC a přerušení na MCU jsou v tomto ohledu totéž: druhý tok řízení, který může udeřit mezi dvěma instrukcemi. Totéž platí pro všechno, co je větší než slovo CPU: 64bitové časové razítko nebo struktura se dvěma poli se může přečíst napůl staré a napůl nové (<em>torn read</em>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tři-způsoby-řešení">Tři způsoby řešení<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#t%C5%99i-zp%C5%AFsoby-%C5%99e%C5%A1en%C3%AD" class="hash-link" aria-label="Přímý odkaz na Tři způsoby řešení" title="Přímý odkaz na Tři způsoby řešení" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-jeden-zapisovatel-pro-každou-proměnnou-nejlepší">1. Jeden zapisovatel pro každou proměnnou (nejlepší)<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#1-jeden-zapisovatel-pro-ka%C5%BEdou-prom%C4%9Bnnou-nejlep%C5%A1%C3%AD" class="hash-link" aria-label="Přímý odkaz na 1. Jeden zapisovatel pro každou proměnnou (nejlepší)" title="Přímý odkaz na 1. Jeden zapisovatel pro každou proměnnou (nejlepší)" translate="no">​</a></h3>
<p>Nejrobustnější řešení je navrhnout data tak, aby <strong>každou proměnnou zapisovala jen jedna strana</strong>. Přerušení zapisuje příznak, hlavní kód ho jen čte a nemaže (nebo naopak). Bez dvou zapisovatelů není co ztratit. Pokud obě strany potřebují měnit tutéž věc, neměly by ji sdílet: každá má vlastní proměnnou (čítač přerušení je <code>isrCalls</code>, čítač hlavního kódu je jiný) a součet vytvoří čtenář.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-kritická-sekce">2. Kritická sekce<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#2-kritick%C3%A1-sekce" class="hash-link" aria-label="Přímý odkaz na 2. Kritická sekce" title="Přímý odkaz na 2. Kritická sekce" translate="no">​</a></h3>
<p>Když se dvěma zapisovatelům nelze vyhnout, přerušení se na dobu operace zakážou. Správný způsob je <strong>uložit stav a obnovit ho</strong>, a ne na konci slepě přerušení povolit, protože funkce mohla být zavolána s již zakázanými přerušeními:</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>Cenou je latence: během sekce nemůže běžet žádné přerušení. Sekce proto musí být krátká jako pár instrukcí a bez volání funkce, smyčky nebo čekání uvnitř.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-atomická-operace">3. Atomická operace<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#3-atomick%C3%A1-operace" class="hash-link" aria-label="Přímý odkaz na 3. Atomická operace" title="Přímý odkaz na 3. Atomická operace" translate="no">​</a></h3>
<p>Pro jediné slovo (čítač, příznak s počtem) má procesor instrukce <code>LDREX</code> a <code>STREX</code>: uložení uspěje, jen pokud se adresy od načtení nic nedotklo, a když ne, smyčka se opakuje. Překladač je za vás vygeneruje ze standardní operace:</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>v C je to jeden řádek, <code>__atomic_fetch_add(&amp;counter, 1u, __ATOMIC_RELAXED)</code> (nebo <code>atomic_fetch_add()</code> z <code>&lt;stdatomic.h&gt;</code>). Nezakazuje přerušení, takže nepřidává latenci. Funguje pro jedinou proměnnou; pro dvě proměnné, které patří k sobě, nepomůže.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="nejpoužívanější-vzor-kruhový-buffer">Nejpoužívanější vzor: kruhový buffer<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#nejpou%C5%BE%C3%ADvan%C4%9Bj%C5%A1%C3%AD-vzor-kruhov%C3%BD-buffer" class="hash-link" aria-label="Přímý odkaz na Nejpoužívanější vzor: kruhový buffer" title="Přímý odkaz na Nejpoužívanější vzor: kruhový buffer" translate="no">​</a></h2>
<p>Nejčastější věc, kterou přerušení předává hlavnímu kódu, je proud dat: bajty přijaté UARTem, vzorky ADC. Přerušení je nemůže zpracovat (musí být krátké), a tak je vloží do <strong>fronty</strong> a hlavní kód je vybere v klidné chvíli. Je to problém producent-konzument s <em>jedním producentem</em> (přerušení) a <em>jedním konzumentem</em> (hlavní kód) a právě pro tento případ kruhový buffer <strong>nepotřebuje žádný zámek</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>Proč je správný?</p>
<ul>
<li class=""><code>head</code> zapisuje <strong>jen producent</strong> a <code>tail</code> <strong>jen konzument</strong>. Neexistuje proměnná se dvěma zapisovateli, takže se nemůže ztratit žádná aktualizace: je to první řešení výše, zabudované do struktury.</li>
<li class="">Čítače jsou volně běžící (nikdy se neresetují). Počet položek je <code>head - tail</code> a díky aritmetice bez znaménka je správný i po přetečení čítačů. Při velikosti, která je mocninou dvou, je pozice jednoduchá maska místo dělení.</li>
<li class="">Záleží na <strong>pořadí</strong>: producent zapíše položku a <strong>teprve potom</strong> ji zveřejní posunutím <code>head</code> (<code>memory_order_release</code>) a konzument čte nejprve <code>head</code> (<code>memory_order_acquire</code>) a až potom položku. Na jednom jádru Cortex-M záleží jen na pořadí, v jakém překladač zapisuje, a atomiky ho zachovávají. Na MCU se dvěma jádry (některé STM32H7 mají dvě) nebo s cache je stejný kód stále správný, a to je důvod, proč ho psát v této podobě a ne s <code>volatile</code>, které náhodou funguje.</li>
<li class="">Producent nečeká. Plný buffer znamená „zahoď položku a započítej to“, protože přerušení nemůže na nikoho čekat. Čítač zahozených položek vám v testu řekne, že buffer je příliš malý.</li>
</ul>
<p>Otestoval jsem ho dvěma způsoby. Na PC se dvěma vlákny, producentem a konzumentem, projde 20 milionů položek bufferem o 16 slotech:</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>a na Cortex-M4 v QEMU: přerušení SysTick je producent a <code>main()</code> konzument, s 5000 položkami:</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>První test je těžší (obě vlákna skutečně běží paralelně na dvou jádrech), druhý je skutečná situace MCU. Je to také ideální kandidát na unit test na PC, jako v článku o <a class="" href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock">unit testování s Unity a CMock</a>: modul je nezávislý na hardwaru.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pravidla-pro-obsluhu-přerušení">Pravidla pro obsluhu přerušení<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#pravidla-pro-obsluhu-p%C5%99eru%C5%A1en%C3%AD" class="hash-link" aria-label="Přímý odkaz na Pravidla pro obsluhu přerušení" title="Přímý odkaz na Pravidla pro obsluhu přerušení" translate="no">​</a></h2>
<ol>
<li class=""><strong>Krátká.</strong> Přečíst registr, uložit data, nastavit příznak, vymazat pending flag, vrátit se. Zpracování se dělá v hlavním kódu.</li>
<li class=""><strong>Žádné čekání, žádná alokace, žádný <code>printf</code>.</strong> Nic, co blokuje, trvá dlouho nebo volá funkci, která není bezpečná pro volání z přerušení (je <em>non-reentrant</em>, pokud uvnitř používá statický buffer).</li>
<li class=""><strong>Vše sdílené je <code>volatile</code> nebo atomické</strong> a každá proměnná má definovaného zapisovatele.</li>
<li class=""><strong>Nesdílejte víc, než musíte.</strong> Příznak nebo fronta mezi stranami, ne struktura o deseti polích.</li>
<li class=""><strong>Myslete na prioritu.</strong> Přerušení s vyšší prioritou může přerušit jiné přerušení. Proměnná sdílená mezi dvěma přerušeními má stejný problém jako ta sdílená s hlavním kódem.</li>
</ol>
<p>V BSP Embedbits mají periferní moduly (např. USART) variantu zpracování dat s pollingem, s přerušením a s DMA a varianta s přerušením je přesně tohle: handler na úrovni MCAL, který vezme data z periferie a předá je aplikaci přes buffer, zatímco <code>Task</code> modulu běží v hlavní smyčce a provádí zpracování.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shrnutí">Shrnutí<a href="https://embedbits.cz/cs/blog/interrupts-and-main-shared-data#shrnut%C3%AD" class="hash-link" aria-label="Přímý odkaz na Shrnutí" title="Přímý odkaz na Shrnutí" translate="no">​</a></h2>



































<table><thead><tr><th>Problém</th><th>Příznak</th><th>Lék</th></tr></thead><tbody><tr><td>Překladač nevidí přerušení</td><td>Funguje s <code>-O0</code>, nekonečná smyčka s <code>-O2</code></td><td><code>volatile</code> na každé sdílené proměnné</td></tr><tr><td><code>counter++</code> není atomické</td><td>Počet, který je občas příliš malý</td><td>Jeden zapisovatel na proměnnou, kritická sekce nebo <code>atomic_fetch_add</code></td></tr><tr><td>Více než slovo</td><td>Napůl stará, napůl nová hodnota</td><td>Kritická sekce, sekvenční číslo nebo fronta</td></tr><tr><td>Proud dat</td><td>Ztracené nebo promíchané bajty</td><td>Kruhový buffer s jedním producentem a jedním konzumentem</td></tr><tr><td>Test projde v simulátoru</td><td>Chyba v terénu</td><td>Pamatujte, že simulátor přerušuje na jiných místech než MCU</td></tr></tbody></table>
<p>Tři druhy kódu v tomto článku měly jedno společné: všechny <em>vypadaly</em> správně.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>STM32</category>
        </item>
        <item>
            <title><![CDATA[Konečné automaty v praxi: tlačítko s debounce a dlouhým stiskem]]></title>
            <link>https://embedbits.cz/cs/blog/fsm-in-practice-button</link>
            <guid>https://embedbits.cz/cs/blog/fsm-in-practice-button</guid>
            <pubDate>Tue, 06 Oct 2026 10:00:00 GMT</pubDate>
            <description><![CDATA[V prvním článku o konečných automatech jsem vám dal šablonu a skončil jsem slovy „pokračování příště“. Tohle je to pokračování a nejlepší způsob, jak pokračovat po teorii, je problém. Vybral jsem takový, který má každý embedded projekt a který nikdo nenapíše správně na první pokus: tlačítko.]]></description>
            <content:encoded><![CDATA[<p>V <a class="" href="https://embedbits.cz/cs/blog/finite-state-machines">prvním článku o konečných automatech</a> jsem vám dal šablonu a skončil jsem slovy „pokračování příště“. Tohle je to pokračování a nejlepší způsob, jak pokračovat po teorii, je problém. Vybral jsem takový, který má každý embedded projekt a který nikdo nenapíše správně na první pokus: <strong>tlačítko</strong>.</p>
<p>Tlačítko vypadá triviálně: pin, high nebo low. Jenže mechanický kontakt <em>zakmitává</em>, takže pin udělá 1 0 1 1 0 1, než se ustálí, a produkt obvykle chce od stejného tlačítka dvě různé věci: krátký a dlouhý stisk. Napsané pomocí příznaků a čítačů v hlavní smyčce to skončí jako pár <code>if</code>ů, které na sobě závisejí způsobem, který po měsíci nikdo nevysvětlí. Konečný automat to vyřeší tak, že to vysvětlíte tabulkou.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="šablona-v-jednom-odstavci">Šablona v jednom odstavci<a href="https://embedbits.cz/cs/blog/fsm-in-practice-button#%C5%A1ablona-v-jednom-odstavci" class="hash-link" aria-label="Přímý odkaz na Šablona v jednom odstavci" title="Přímý odkaz na Šablona v jednom odstavci" translate="no">​</a></h2>
<p>Každý stav má čtyři rutiny a každá z nich má právě jeden úkol:</p>






























<table><thead><tr><th>Rutina</th><th>Volá se</th><th>Úkol</th></tr></thead><tbody><tr><td><code>Entry</code></td><td>jednou, při vstupu do stavu</td><td>připravit stav (vynulovat čítač, vytvořit událost)</td></tr><tr><td><code>Execute</code></td><td>při každém běhu automatu, dokud je ve stavu</td><td>udělat práci stavu (počítat, vzorkovat)</td></tr><tr><td><code>CheckLeave</code></td><td>při každém běhu, po <code>Execute</code></td><td>rozhodnout, zda stav opustit a kam: <strong>jediné místo, kde se žádá o přechod</strong></td></tr><tr><td><code>Leave</code></td><td>jednou, při opuštění stavu</td><td>uklidit</td></tr></tbody></table>
<p>Jádro automatu spouští <code>Execute</code> a <code>CheckLeave</code> aktuálního stavu a když se stav změnil, spustí <code>Leave</code> starého a <code>Entry</code> nového. Rutiny se nikdy nevolají navzájem a kód automatu neobsahuje nic jiného než automat. Pokud chcete vědět, proč je zařízení v nějakém stavu, přečtete si <code>CheckLeave</code> předchozího.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="nejdřív-návrh-stavy-a-přechody">Nejdřív návrh: stavy a přechody<a href="https://embedbits.cz/cs/blog/fsm-in-practice-button#nejd%C5%99%C3%ADv-n%C3%A1vrh-stavy-a-p%C5%99echody" class="hash-link" aria-label="Přímý odkaz na Nejdřív návrh: stavy a přechody" title="Přímý odkaz na Nejdřív návrh: stavy a přechody" translate="no">​</a></h2>
<p>Úloha běží každých 10 ms a čte surový kontakt. Doba debounce je 50 ms a hranice dlouhého stisku je 1 sekunda. Stačí pět stavů:</p>





















































<table><thead><tr><th>Stav</th><th>Execute</th><th>Opouští se, když</th><th>Kam</th></tr></thead><tbody><tr><td><code>RELEASED</code></td><td>nic</td><td>kontakt je sepnutý</td><td><code>DEBOUNCE_PRESS</code></td></tr><tr><td><code>DEBOUNCE_PRESS</code></td><td>počítá tiky</td><td>kontakt se opět rozepne (byl to glitch)</td><td><code>RELEASED</code></td></tr><tr><td></td><td></td><td>kontakt byl sepnutý 50 ms</td><td><code>PRESSED</code></td></tr><tr><td><code>PRESSED</code></td><td>počítá tiky</td><td>kontakt se rozepne: událost <strong>krátký stisk</strong></td><td><code>DEBOUNCE_RELEASE</code></td></tr><tr><td></td><td></td><td>kontakt je sepnutý 1 s</td><td><code>LONG_PRESS</code></td></tr><tr><td><code>LONG_PRESS</code></td><td>nic, událost <strong>dlouhý stisk</strong> vznikla při vstupu</td><td>kontakt se rozepne</td><td><code>DEBOUNCE_RELEASE</code></td></tr><tr><td><code>DEBOUNCE_RELEASE</code></td><td>počítá tiky rozepnutého kontaktu, zakmitnutí vynuluje počet</td><td>kontakt byl rozepnutý 50 ms</td><td><code>RELEASED</code></td></tr></tbody></table>
<p>Skutečná práce je napsat tabulku. Když je úplná, kód je jen cvičení v psaní. Když není (co se stane ve stavu <code>LONG_PRESS</code>, když kontakt při uvolnění zakmitne?), tabulka ukáže díru dřív, než napíšete řádek C.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kód">Kód<a href="https://embedbits.cz/cs/blog/fsm-in-practice-button#k%C3%B3d" class="hash-link" aria-label="Přímý odkaz na Kód" title="Přímý odkaz na Kód" translate="no">​</a></h2>
<p>Vstup přichází z BSP, takže modul nemá žádnou závislost na hardwaru a dá se testovat na PC (stejné <em>švy</em> jako v článku o <a class="" href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock">unit testování</a>). Port modulu tvoří <code>Init</code>, <code>Task</code> a funkce, která vrátí událost jednou:</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>Typy sledují šablonu. Jednu změnu jsem udělal záměrně: tabulka rutin je <strong>indexovaná stavem</strong> a nehledá se v ní, a výčet končí hodnotou <code>BUTTON_STATE_COUNT</code>, která má dvojí využití.</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>První využití je samotná tabulka. S designated initializers nezáleží na pozici řádku, takže stav nelze propojit se špatnými rutinami, když někdo přidá řádek doprostřed (šablona potřebuje komentář „toto pole musí mít stejné pořadí jako výčet stavů“):</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>Druhé využití je jádro automatu, ve kterém stejná konstanta nahrazuje napevno zapsaný „poslední stav“ při kontrole rozsahu:</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>Všimněte si, co jádro <em>neví</em>: tlačítka, čas, události. Teď stavy. Většina rutin jsou jednořádkové:</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>Několik detailů, které stojí za pozornost:</p>
<ul>
<li class=""><code>Button_Task()</code> čte vstup <strong>jednou</strong> za běh a uchovává ho v <code>isContactClosed</code>. Všechny rutiny jednoho běhu vidí stejnou hodnotu, i když se pin uprostřed běhu změní.</li>
<li class="">Událost krátkého stisku vzniká v <code>Button_Pressed_CheckLeave()</code>, na stejném místě, kde se dělá rozhodnutí. Událost dlouhého stisku vzniká v <code>Button_LongPress_Entry()</code>: entry se volá přesně jednou na přechod, takže událost nemůže vzniknout dvakrát, ať kontakt dělá při držení tlačítka cokoli.</li>
<li class="">Debounce uvolnění (<code>DEBOUNCE_RELEASE</code>) vynuluje čítač pokaždé, když se kontakt znovu sepne. To je odpověď na zakmitání při uvolnění: automat počká, až je kontakt 50 ms v klidu.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="test">Test<a href="https://embedbits.cz/cs/blog/fsm-in-practice-button#test" class="hash-link" aria-label="Přímý odkaz na Test" title="Přímý odkaz na Test" translate="no">​</a></h2>
<p>Test nahradí <code>Bsp_Get_ButtonRaw()</code> funkcí, která čte řetězec: jeden znak na tik po 10 ms, <code>1</code> je sepnutý kontakt. Vzorky jsou příběhem tlačítka a výsledkem je řetězec událostí, <code>S</code> pro krátký stisk a <code>L</code> pro dlouhý:</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>Výstup běhu je skutečný:</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>Poslední dva řádky jsou případ, který příznaky vždycky pokazí. Držení 1,5 sekundy vyvolá <strong>jeden</strong> dlouhý stisk a po uvolnění žádný krátký a držení těsně pod hranicí je krátký stisk. Obojí je důsledkem tabulky, a ne pečlivého programování.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-získáte-a-co-to-stojí">Co získáte a co to stojí<a href="https://embedbits.cz/cs/blog/fsm-in-practice-button#co-z%C3%ADsk%C3%A1te-a-co-to-stoj%C3%AD" class="hash-link" aria-label="Přímý odkaz na Co získáte a co to stojí" title="Přímý odkaz na Co získáte a co to stojí" translate="no">​</a></h2>
<p><strong>Získáte:</strong></p>
<ul>
<li class=""><strong>čitelnou specifikaci</strong>: tabulka výše a kód jsou totéž,</li>
<li class=""><strong>záruku jednorázovosti</strong>: <code>Entry</code> a <code>Leave</code> běží jednou na přechod, události se neduplikují,</li>
<li class=""><strong>místo pro všechno</strong>: nový požadavek (dvojklik) je nový stav nebo nový řádek v tabulce, a ne úprava tří vnořených podmínek,</li>
<li class=""><strong>automat, který lze testovat na PC</strong> s řetězcem jako vstupem, jak jste právě viděli.</li>
</ul>
<p><strong>Stojí to:</strong></p>
<ul>
<li class=""><strong>boilerplate</strong>: čtyři funkce na stav, většina z nich prázdná. Je to cena za jednotnost a vyplatí se od pátého stavu. Pro automat se dvěma stavy je lepší <code>switch</code>,</li>
<li class=""><strong>tabulku přechodů je třeba promyslet</strong> dřív, než napíšete kód. To není cena, ale na začátku tak působí.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="úskalí">Úskalí<a href="https://embedbits.cz/cs/blog/fsm-in-practice-button#%C3%BAskal%C3%AD" class="hash-link" aria-label="Přímý odkaz na Úskalí" title="Přímý odkaz na Úskalí" translate="no">​</a></h2>
<ol>
<li class=""><strong>Čas patří periodě tasku, ne zpoždění.</strong> Automat počítá běhy, takže limity (50 ms, 1 s) jsou počty tiků. Nikdy ve stavu nevolejte delay, zablokuje všechny ostatní automaty.</li>
<li class=""><strong>Vzorkujte v tasku, ne v přerušení.</strong> Přerušení od pinu by vidělo každé zakmitnutí. Task běžící každých 10 ms je dolní propust zdarma.</li>
<li class=""><strong>Jediný slot pro událost ztrácí události,</strong> pokud je aplikace čte pomaleji, než je automat vyrábí. U tlačítka to nevadí, u protokolu ano: použijte frontu.</li>
<li class=""><strong>Neplatný stav je také stav.</strong> Kontrola rozsahu v jádře pošle poškozenou proměnnou do bezpečného stavu místo čtení tabulky mimo její meze (platí zde pravidla MISRA o <a class="" href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice">nedefinovaném chování</a>).</li>
<li class=""><strong>Automat s 30 stavy je znamením chybějící hierarchie.</strong> Rozdělte ho na několik automatů, kde jeden je <em>stavem</em> druhého, a každý udržte tak malý, aby se tabulka vešla na jednu obrazovku.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="opravy-v-šabloně">Opravy v šabloně<a href="https://embedbits.cz/cs/blog/fsm-in-practice-button#opravy-v-%C5%A1ablon%C4%9B" class="hash-link" aria-label="Přímý odkaz na Opravy v šabloně" title="Přímý odkaz na Opravy v šabloně" translate="no">​</a></h2>
<p>Když jsem příklad porovnal se šablonou z prvního článku, našel jsem v šabloně dva přeřeky a opravil jsem je tam (pozdější revize šablony našla další, viz <a class="" href="https://embedbits.cz/cs/blog/finite-state-machines#what-was-fixed">seznam oprav</a>): počáteční hodnota stavových proměnných byla zbytkový název z jiného projektu (<code>APPCORE_HANDLER_STATE_1</code> místo <code>&lt;MODULE&gt;_STATE_1</code>) a poslední řádek tabulky používal <code>State_2_Leave</code> místo <code>State_3_Leave</code>. Druhá z nich je druh chyby, o které tento článek je: kód se přeloží a automat při opuštění třetího stavu zavolá špatnou rutinu. Tabulka s designated initializers to trochu ztěžuje a test, který projde všechny stavy, to znemožňuje.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>Architektura</category>
        </item>
        <item>
            <title><![CDATA[Jeden BSP, mnoho rodin STM32: proč Git větve a kolik stojí]]></title>
            <link>https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches</link>
            <guid>https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches</guid>
            <pubDate>Mon, 05 Oct 2026 18:00:00 GMT</pubDate>
            <description><![CDATA[STM32 není jeden mikrokontrolér, je to tucet rodin: G4, H5, U5, F4 a tak dále. Mají stejné jádro Cortex-M, ale jiné periferie, jiné názvy registrů a jiný balík ovladačů od výrobce. Pokud chcete, aby jedna architektura firmwaru běžela na všech, musíte se rozhodnout, kde budou rozdíly žít. Žádná varianta není zadarmo. Tento článek popisuje tu, kterou jsem zvolil pro BSP Embedbits, co o ní říkají čísla ze skutečných repozitářů a kolik stojí.]]></description>
            <content:encoded><![CDATA[<p>STM32 není jeden mikrokontrolér, je to tucet rodin: G4, H5, U5, F4 a tak dále. Mají stejné jádro Cortex-M, ale jiné periferie, jiné názvy registrů a jiný balík ovladačů od výrobce. Pokud chcete, aby jedna architektura firmwaru běžela na všech, musíte se rozhodnout, kde budou rozdíly žít. Žádná varianta není zadarmo. Tento článek popisuje tu, kterou jsem zvolil pro BSP Embedbits, co o ní říkají čísla ze skutečných repozitářů a kolik stojí.</p>
<!-- -->
<p>Všechna čísla níže pocházejí z repozitářů ze dne 5. října 2026, změřená malým skriptem, který najdete na konci části o nákladech. Poznámka k datu: v tu chvíli je <strong>STM32F4 jedinou rodinou s kompletním vydáním</strong> BSP a vydání ostatních (jako první U5) se právě připravovalo. Čísla tedy ukazují platformu uprostřed migrace, ne konečný stav, a právě to je činí zajímavými. Spusťte skript znovu po vydání a porovnejte.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="čtyři-způsoby-jak-podporovat-mnoho-rodin">Čtyři způsoby, jak podporovat mnoho rodin<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#%C4%8Dty%C5%99i-zp%C5%AFsoby-jak-podporovat-mnoho-rodin" class="hash-link" aria-label="Přímý odkaz na Čtyři způsoby, jak podporovat mnoho rodin" title="Přímý odkaz na Čtyři způsoby, jak podporovat mnoho rodin" translate="no">​</a></h2>






























<table><thead><tr><th>Přístup</th><th>Jak vypadá</th><th>Problém</th></tr></thead><tbody><tr><td><strong>Jeden strom, <code>#ifdef</code></strong></td><td><code>#if defined(STM32G4) ... #elif defined(STM32U5) ...</code> v kódu</td><td>Kód se zaplní podmínkami, jejich většina je pro konkrétní build mrtvá (viz pravidla o mrtvém kódu v článku o <a class="" href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice">MISRA</a>) a nikdo se jich neodváží dotknout</td></tr><tr><td><strong>Copy-paste</strong></td><td>Složka pro každou rodinu, kopie všeho</td><td>Každou opravu je nutné udělat N-krát ručně a jedna z nich se zapomene</td></tr><tr><td><strong>Jeden repozitář na rodinu</strong></td><td><code>Bsp-G4</code>, <code>Bsp-U5</code>, ...</td><td>Totéž co kopie, jen s více repozitáři</td></tr><tr><td><strong>Abstrakce + větev pro každou rodinu</strong></td><td>Jedno rozhraní, rodina žije ve větvi</td><td>Větev se může od ostatních vzdálit (viz níže)</td></tr></tbody></table>
<p>Používám tu poslední. Myšlenka je, že uživatel vybere rodinu <strong>jednou</strong> a od té chvíle strom obsahuje už jen kód této rodiny.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="jak-to-funguje-v-bsp">Jak to funguje v BSP<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#jak-to-funguje-v-bsp" class="hash-link" aria-label="Přímý odkaz na Jak to funguje v BSP" title="Přímý odkaz na Jak to funguje v BSP" translate="no">​</a></h2>
<p>Každá rodina STM32 je <strong>Git větev</strong> repozitáře BSP (<code>STM32G4</code>, <code>STM32H5</code>, <code>STM32U5</code>, ...). Totéž platí pro moduly BSP: moduly MCAL, linker a RAL. Zbytek obstará platforma. Když spustíte instalační skript EmBi_Platform a vyberete <em>Configure BSP module</em>, vypíše větve:</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>a po vašem výběru přidá moduly BSP jako Git submoduly, přepne na větev a commity dané rodiny a aktualizuje soubory CMake. Projekt je připnutý na konkrétní commity, takže se zítra sestaví stejně. Položky s <code>_Dev</code> jsou vývojové větve rodiny a <code>master</code> obsahuje nejnovější nevydané změny všech rodin, je tedy určen pro práci na platformě, ne pro produkt. Přepnutí na jinou rodinu znamená spustit stejnou volbu znovu.</p>
<p>Balík ovladačů výrobce se řídí stejným schématem. RAL má větve <code>STM32&lt;family&gt;</code> pro rodinu, <code>STM32&lt;family&gt;_&lt;major&gt;.x</code> pro hlavní vydání ovladačů ST a <code>STM32&lt;family&gt;_&lt;major&gt;.&lt;minor&gt;</code> pro vedlejší. Když ST zveřejní novou verzi, vznikne nová větev a stará zůstane dostupná pro projekty, které ji používají.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kde-jsou-rozdíly-doopravdy">Kde jsou rozdíly doopravdy<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#kde-jsou-rozd%C3%ADly-doopravdy" class="hash-link" aria-label="Přímý odkaz na Kde jsou rozdíly doopravdy" title="Přímý odkaz na Kde jsou rozdíly doopravdy" translate="no">​</a></h2>
<p>Chtěl jsem vědět, kolik kódu se mezi rodinami skutečně liší, a tak jsem porovnal větve. Tady je modul GPIO, <code>Bsp-Mcal-Gpio</code>, s vydanou STM32F4 jako referencí. Čísla jsou změněné řádky (přidané plus odebrané) v každém souboru:</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>Veřejné rozhraní, <code>Gpio_Port.h</code>, je na F4 a H5 <strong>totožné</strong> a na G4 a U5 se liší ve třech řádcích komentáře. G4 a U5 jsou si navzájem blízké (jejich <code>Gpio.c</code> se liší ve třech řádcích, opět jen komentář): jde o starší generaci modulu, která čeká na vydání. Proč je <em>kód modulu</em> tak podobný u dvou různých rodin? Protože rozdíl byl vyňat z modulu do nejnižší vrstvy. RAL má složku <code>Port</code> s jednou hlavičkou pro každou periferii a celý rozdíl mezi rodinami v <code>Stm32_gpio.h</code> je tento:</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>Jeden řádek. Modul MCAL vkládá <code>Stm32_gpio.h</code> a nikdy neví, jaký ovladač výrobce je za ním. Totéž platí pro další periferie, které jsem porovnal mezi G4 a U5 (<code>Stm32_rcc.h</code>, <code>Stm32_usart.h</code>, <code>Stm32_tim.h</code>): dva odlišné řádky z 32. To je celá myšlenka vrstvené architektury, aplikovaná na otázku rodin.</p>
<p>Co se liší, jsou <strong>sady periferií</strong>. Složka <code>Port</code> pro G4 obsahuje hlavičky pro HRTIM a DMAMUX, které U5 nemá, a U5 má cache, PKA, SDMMC a low-power GPIO, které G4 nemá. Modul pro periferii, kterou rodina nemá, ve své větvi prostě není, a odtud pochází tabulka <em>podpora rodin</em> na stránce o <a class="" href="https://embedbits.cz/cs/docs/bsp/mcal">MCAL</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="dvě-úrovně-rodina-a-mcu">Dvě úrovně: rodina a MCU<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#dv%C4%9B-%C3%BArovn%C4%9B-rodina-a-mcu" class="hash-link" aria-label="Přímý odkaz na Dvě úrovně: rodina a MCU" title="Přímý odkaz na Dvě úrovně: rodina a MCU" translate="no">​</a></h3>
<p>Větev řeší rozdíl mezi <em>rodinami</em>. Menší rozdíl existuje <em>uvnitř</em> rodiny: jednotlivé MCU mají různý počet portů (MCU v malém pouzdře má méně portů GPIO než to ve velkém). To se řeší podmínkou na makrech, která hlavičkový soubor zařízení od výrobce už definuje, ne větví:</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>a v typech je neexistující port namapován na hodnotu <code>GPIO_PORT_CNT</code>, takže ostatní moduly se stále překládají a použití takového portu lze rozpoznat jako neplatné. Pravidlo: <strong>větev pro jinou rodinu, <code>#if defined</code> na makro výrobce pro jiné MCU ve stejné rodině.</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-získáte">Co získáte<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#co-z%C3%ADsk%C3%A1te" class="hash-link" aria-label="Přímý odkaz na Co získáte" title="Přímý odkaz na Co získáte" translate="no">​</a></h2>
<ul>
<li class=""><strong>Pouze kód dané rodiny.</strong> Žádné lesy <code>#ifdef</code>, nic není mrtvé a diff změny ukazuje jen kód, který se skutečně sestavuje.</li>
<li class=""><strong>Čisté oddělení kódu výrobce.</strong> Ovladače ST pro každou rodinu jsou zrcadleny ve vlastních větvích RAL a nejsou upravovány. Váš kód je neobsahuje.</li>
<li class=""><strong>Stabilní rozhraní pro aplikaci.</strong> Aplikace volá <code>Gpio_Set_PinLevel()</code> a rodinu nezná, takže změna MCU je jiná větev, ne přepsání aplikace.</li>
<li class=""><strong>Připnuté verze.</strong> Projekt přesně říká, který commit které větve používá, takže aktualizace je vědomé rozhodnutí.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kolik-to-stojí-drift">Kolik to stojí: drift<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#kolik-to-stoj%C3%AD-drift" class="hash-link" aria-label="Přímý odkaz na Kolik to stojí: drift" title="Přímý odkaz na Kolik to stojí: drift" translate="no">​</a></h2>
<p>Slabinou větví je, že žijí vlastním životem. Oprava provedená v jedné větvi není v ostatních, dokud ji tam někdo nepřenese. Výše uvedené měření ukazuje současně dvě <em>generace</em> téhož modulu. Vydané F4 (a H5, které po něm následuje) má vylepšenou inicializaci GPIO (výstupní úroveň se nastaví <em>před</em> přepnutím pinu do režimu výstupu, takže pin nezakmitá), zdokumentované parametry a složku <code>Tests</code> s <strong>unit testy a integračními testy</strong>. G4 a U5 nic z toho zatím nemají. Veřejné rozhraní USART v <code>Usart_Port.h</code> to ukazuje ještě lépe:</p>






























<table><thead><tr><th>Větev</th><th>Veřejné funkce</th><th>Ve srovnání s F4</th></tr></thead><tbody><tr><td>STM32F4 (vydaná)</td><td>79</td><td>reference</td></tr><tr><td>STM32H5</td><td>79</td><td>stejná sada funkcí, hlavička se liší ve 2 řádcích</td></tr><tr><td>STM32G4</td><td>82</td><td>12 funkcí, které F4 nemá (<code>Usart_StartTransmit</code>, <code>Usart_Set_TransmitBytes</code>, ...) a 9, které F4 má a G4 ne (<code>Usart_Set_TxStart</code>, <code>Usart_Set_DataConfig</code>, ...)</td></tr><tr><td>STM32U5</td><td>83</td><td>13 funkcí jen na U5, 9 jen na F4</td></tr></tbody></table>
<p>V tuto chvíli se kód napsaný proti rozhraní F4 přeloží na H5 a nepřeloží na G4 a U5. To není chyba přístupu, je to běžný stav platformy uprostřed vydání. Ukazuje to ale cenu: slib „stejné rozhraní BSP pro všechny rodiny“ platí pro rodinu až <strong>po vydání její větve</strong> a doba mezi vydáním první a poslední rodiny je období, kdy se větve od sebe vzdalují. Během něj by nikdo neměl psát aplikaci pro rodinu, která není připravená.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="jak-držet-drift-pod-kontrolou">Jak držet drift pod kontrolou<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#jak-dr%C5%BEet-drift-pod-kontrolou" class="hash-link" aria-label="Přímý odkaz na Jak držet drift pod kontrolou" title="Přímý odkaz na Jak držet drift pod kontrolou" translate="no">​</a></h3>
<ol>
<li class=""><strong>Mějte referenční větev a seznam toho, co je portováno.</strong> Jedna rodina vede (zde F4), ostatní následují a stav je viditelný: to je tabulka podpory rodin na stránce MCAL, rozšířená o „stejná verze rozhraní jako reference“.</li>
<li class=""><strong>Udělejte z vydání jednu operaci.</strong> Release skript, který projde všechny moduly jedné rodiny (tak, jak se dělá vydání U5), je lepší než ručně provedený merge: rodina je buď připravená celá, nebo není.</li>
<li class=""><strong>Měřte drift.</strong> Skript níže porovná jeden modul na několika větvích a vypíše počet změněných řádků na soubor. Nula nebo komentář znamená „stejné“, velké číslo je práce, která čeká. Trvá to vteřinu a vejde se to do CI jobu.</li>
<li class=""><strong>Nechte jednu sadu testů kontrolovat všechny větve.</strong> Unit testy, které existují na F4 (a H5), jsou specifikací modulu. Pokud musí stejný <code>Test_Gpio.c</code> projít na každé větvi rodiny, rozhraní se nemůže nepozorovaně rozejít. Článek o <a class="" href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock">unit testování</a> ukazuje, jak takový test postavit.</li>
<li class=""><strong>Držte rozdíl dole.</strong> Vše, co lze přesunout do hlaviček <code>Port</code> v RAL (jediný <code>#include</code>, jak je ukázáno výše), je rozdíl, který není třeba udržovat po větvích. Čím více kódu je <em>totožného</em>, tím snazší je převzít opravu z jedné větve do druhé (<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>Použití na větvích modulu GPIO (tabulka výše je jeho výstup):</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>U ostatních modulů je obraz jiný a je užitečné to vědět dříve, než začnete plánovat práci:</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>EXTI má veřejnou hlavičku beze změny na všech větvích a jinou implementaci (periferie se liší, rozhraní ne). USART se liší v rozhraní G4 a U5 a ve velké části implementace, což je měřítko toho, kolik práce vydání těchto dvou obnáší.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="který-přístup-zvolit">Který přístup zvolit<a href="https://embedbits.cz/cs/blog/bsp-stm32-families-git-branches#kter%C3%BD-p%C5%99%C3%ADstup-zvolit" class="hash-link" aria-label="Přímý odkaz na Který přístup zvolit" title="Přímý odkaz na Který přístup zvolit" translate="no">​</a></h2>
<ul>
<li class=""><strong>Větve pro každou rodinu</strong> se hodí, když se rodiny liší v <em>sadě</em> periferií a v ovladačích výrobce, když se produkt staví pro několik rodin a když si můžete dovolit udržovat rozhraní (drift je zvládnutelný s několika rodinami a nástrojem).</li>
<li class=""><strong><code>#ifdef</code> v jednom stromu</strong> je přijatelný, když jsou rozdíly malé: jedna rodina s několika variantami MCU, jediný registr, který se jmenuje jinak.</li>
<li class=""><strong>Ani jeden z nich</strong> nepomůže bez <strong>abstrakce na spodku</strong>. Větev jen rozhoduje, která implementace rozhraní je ve stromu. Pokud aplikace vkládá hlavičky výrobce, větev pro každou rodinu vás před ničím nezachrání.</li>
</ul>
<p>A ať zvolíte cokoli, zapište si, která rodina je referenční, a udržujte v CI jobu jedno číslo: jak daleko jsou ostatní.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>Architektura</category>
            <category>STM32</category>
        </item>
        <item>
            <title><![CDATA[Co se děje před main(): reset, startup kód a linker script]]></title>
            <link>https://embedbits.cz/cs/blog/before-main-startup-linker</link>
            <guid>https://embedbits.cz/cs/blog/before-main-startup-linker</guid>
            <pubDate>Mon, 05 Oct 2026 14:00:00 GMT</pubDate>
            <description><![CDATA[Každý tutoriál jazyka C začíná int main(void). Nikdo ale nevysvětluje, kdo ji volá. A přitom když napíšete uint32_t counter = 5; jako globální proměnnou a první řádek main() přečte 5, už se odvedlo hodně práce. Když se ta práce neodvede, projeví se to proměnnou s náhodnou hodnotou, která „včera fungovala".]]></description>
            <content:encoded><![CDATA[<p>Každý tutoriál jazyka C začíná <code>int main(void)</code>. Nikdo ale nevysvětluje, kdo ji volá. A přitom když napíšete <code>uint32_t counter = 5;</code> jako globální proměnnou a první řádek <code>main()</code> přečte 5, už se odvedlo hodně práce. Když se ta práce neodvede, projeví se to proměnnou s náhodnou hodnotou, která „včera fungovala".</p>
<p>V tomto článku budeme sledovat mikrokontrolér od resetu až po první řádek <code>main()</code>: co udělá hardware sám, co říká linker script a co musí udělat startup kód. Jde o obsah dvou modulů Embedbits BSP (<a class="" href="https://embedbits.cz/cs/docs/bsp/linker">Linker</a> a <a class="" href="https://embedbits.cz/cs/docs/bsp/startup">Startup</a>), ale princip je stejný na každém Cortex-M. Veškerý kód v článku byl přeložen pomocí <code>arm-none-eabi-gcc</code> 13.2.1 a <strong>spuštěn</strong> v QEMU na modelu desky se STM32F405, takže adresy i výstupy jsou skutečné.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-jazyk-c-očekává">Co jazyk C očekává<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#co-jazyk-c-o%C4%8Dek%C3%A1v%C3%A1" class="hash-link" aria-label="Přímý odkaz na Co jazyk C očekává" title="Přímý odkaz na Co jazyk C očekává" translate="no">​</a></h2>
<p>Standard jazyka C slibuje o programu několik věcí, o kterých hardware nic neví:</p>
<ul>
<li class="">globální proměnná s inicializátorem (<code>uint32_t initializedValue = 0x12345678u;</code>) má na začátku tuto hodnotu,</li>
<li class="">globální nebo <code>static</code> proměnná bez inicializátoru je <strong>nulová</strong>,</li>
<li class="">existuje zásobník a funkce ho může používat,</li>
<li class="">globální objekty C++ jsou zkonstruovány (a v C se před <code>main()</code> spustí funkce označené <code>__attribute__((constructor))</code>).</li>
</ul>
<p>Hardware vám dává velmi málo. Po resetu jádro Cortex-M udělá jen dvě věci: z prvního slova vektorové tabulky načte <strong>počáteční hodnotu ukazatele zásobníku</strong>, z druhého <strong>adresu reset handleru</strong>, a skočí tam. Vše ostatní je úkolem startup kódu, který je součástí <strong>vašeho</strong> firmwaru.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vektorová-tabulka">Vektorová tabulka<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#vektorov%C3%A1-tabulka" class="hash-link" aria-label="Přímý odkaz na Vektorová tabulka" title="Přímý odkaz na Vektorová tabulka" translate="no">​</a></h2>
<p>Vektorová tabulka je pole adres umístěné na začátku flash paměti (u STM32 je to <code>0x08000000</code>, což je po bootu z flash vidět i na adrese 0). V minimální podobě obsahuje ukazatel zásobníku, reset handler a handlery výjimek:</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>Takto vypadají prvních 16 bajtů přeloženého firmwaru:</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>Čísla jsou v pořadí little-endian. První slovo je <code>0x20020000</code>, konec 128 kB RAM, která začíná na <code>0x20000000</code>, tedy místo, kde začíná zásobník (roste směrem dolů). Druhé je <code>0x08000013</code>: reset handler leží na <code>0x08000012</code> a nejnižší bit říká „Thumb kód", což je na Cortex-M povinné. Zbytek jsou výjimky; všechny nepoužité jsem nasměroval na stejný handler.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="linker-script-mapa-paměti">Linker script: mapa paměti<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#linker-script-mapa-pam%C4%9Bti" class="hash-link" aria-label="Přímý odkaz na Linker script: mapa paměti" title="Přímý odkaz na Linker script: mapa paměti" translate="no">​</a></h2>
<p>Překladač vytváří objektové soubory se sekcemi (<code>.text</code> pro kód, <code>.data</code>, <code>.bss</code> a tak dále) a netuší, kde v paměti skončí. To rozhoduje linker a potřebuje k tomu mapu. Tady je celý skript z příkladu, 59 řádků:</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>Přečtěme si důležité části.</p>
<p><strong><code>MEMORY</code></strong> popisuje fyzické paměti: kde začínají a jak jsou velké. Atributy říkají linkeru, co je tam povoleno (<code>rx</code>: čtení a spouštění, <code>xrw</code>: všechno).</p>
<p><strong><code>.isr_vector</code> jde do flash jako první</strong> a <code>KEEP</code> brání linkeru, aby ji zahodil: nic v kódu tabulku <em>nevolá</em>, takže by bez <code>KEEP</code> vypadala nepoužitá. Následuje <code>.text</code> s kódem a daty jen pro čtení (<code>.rodata</code>, tedy proměnné <code>const</code> zůstávají ve flash a nespotřebují žádnou RAM).</p>
<p><strong><code>.data</code> je ta zajímavá.</strong> Podívejte se na řádek <code>} &gt; RAM AT &gt; FLASH</code>. Každá sekce má dvě adresy:</p>
<ul>
<li class=""><strong>VMA</strong> (virtual memory address), kde sekce je, když program <em>běží</em>: <code>.data</code> musí být v RAM, protože se do ní zapisuje,</li>
<li class=""><strong>LMA</strong> (load address), kde je sekce <em>uložena</em> v obrazu firmwaru: RAM je po zapnutí napájení prázdná, takže počáteční hodnoty musí ležet někde, kde přežijí, ve flash.</li>
</ul>
<p><code>arm-none-eabi-objdump -h</code> ukáže obě:</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> leží na <code>0x20000000</code>, ale její počáteční hodnoty jsou ve flash na <code>0x080001C4</code>. Někdo je musí zkopírovat, a proto skript definuje symboly <code>_sidata</code> (zdroj ve flash), <code>_sdata</code> a <code>_edata</code> (začátek a konec cíle v RAM). Tyto symboly nemají za sebou žádnou paměť, jsou to pouze adresy, které kód v C čte pomocí <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> je <code>NOLOAD</code>.</strong> V obrazu nemá žádný obsah, jen velikost (proměnná bez inicializátoru s nulovou hodnotou by zbytečně plýtvala flash). Startup kód musí oblast mezi <code>_sbss</code> a <code>_ebss</code> vyplnit nulami.</p>
<p><strong><code>.init_array</code></strong> je tabulka ukazatelů na konstruktory. Startup kód ji projde a konstruktory zavolá.</p>
<p>Linker script v Embedbits BSP generuje CMake pro každé MCU ze šablony. Má stejné symboly (<code>_sidata</code>, <code>_sdata</code>, <code>_edata</code>, <code>_sbss</code>, <code>_ebss</code>, <code>_stack_top</code>) a popisuje i volitelné oblasti, například CCMRAM u STM32G4, kam lze umístit sekci <code>.ccmram</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="startup-kód">Startup kód<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#startup-k%C3%B3d" class="hash-link" aria-label="Přímý odkaz na Startup kód" title="Přímý odkaz na Startup kód" translate="no">​</a></h2>
<p>Skript řekl, kde všechno je, a teď kód udělá to, co jazyk C očekává:</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><code>Reset_Handler</code> má čtyři kroky (části s <code>#ifdef</code> jsou pro experiment níže):</p>
<ol>
<li class=""><strong>Zkopíruje <code>.data</code></strong> z flash (<code>_sidata</code>) do RAM (<code>_sdata</code> až <code>_edata</code>).</li>
<li class=""><strong>Vynuluje <code>.bss</code></strong> (<code>_sbss</code> až <code>_ebss</code>).</li>
<li class=""><strong>Zavolá konstruktory</strong> z <code>.init_array</code>.</li>
<li class=""><strong>Zavolá <code>main()</code></strong>. Pokud by se někdy vrátila, program zůstane v nekonečné smyčce, protože není kam se vrátit.</li>
</ol>
<p>V Embedbits BSP dělá startup modul podle své dokumentace o něco víc: nastaví také hodiny (RCC přes MCAL) a poté zavolá <code>AppMain()</code>. Z pořadí plyne pravidlo: <strong>cokoli se spouští před kroky 1 a 2, nesmí sahat na globální proměnnou</strong>, protože její obsah ještě není platný. Nastavení hodin je funkce, která používá jen registry, nebo si překladač drží stav v lokálních proměnných.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="experiment-co-se-stane-bez-toho">Experiment: co se stane bez toho<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#experiment-co-se-stane-bez-toho" class="hash-link" aria-label="Přímý odkaz na Experiment: co se stane bez toho" title="Přímý odkaz na Experiment: co se stane bez toho" translate="no">​</a></h2>
<p>Aplikace v příkladu má čtyři globální proměnné čtyř druhů:</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>(Část nad tímto, s funkcemi tisknoucími přes <em>semihosting</em>, je pár řádků kódu, které žádají QEMU o vypsání textu a o ukončení. Pro téma není důležitá.)</p>
<p>Nejdřív normální build. Výsledek:</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>Všechny čtyři hodnoty jsou takové, jak jazyk C slibuje, a adresy potvrzují celý příběh: proměnná v RAM je na <code>0x2000...</code>, konstanta ve flash na <code>0x0800...</code>.</p>
<p>Teď experiment. Po resetu běžícího systému není RAM prázdná: obsahuje to, co v ní bylo předtím. Studený start MCU je často „šťastný", protože RAM je náhodou nulová, a chyba ve startup kódu pak zůstane dlouho skrytá. Pro test jsem RAM znečistil (<code>-DDEMO_DIRTY_RAM</code> ji před čímkoli jiným naplní hodnotou <code>0xA5A5A5A5</code>) a potom jsem odstranil kroky 1 a 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>Podívejte se, co je špatně a co ne:</p>
<ul>
<li class=""><code>initializedValue</code> a <code>zeroedValue</code> jsou smetí. První nemá počáteční hodnotu, druhá není nulová, přestože oba řádky v souboru C říkají něco jiného.</li>
<li class=""><code>constantValue</code> je v pořádku, protože je ve flash a nikdo ji nemusí kopírovat.</li>
<li class=""><code>constructedValue</code> je v pořádku, protože ji konstruktor zapsal <em>po</em> (chybějící) inicializaci. Proto se tento druh chyby hledá tak těžko: jedna polovina programu funguje a druhá má náhodné hodnoty.</li>
</ul>
<p>Se znečištěnou RAM a kompletním startup kódem vypíše stejný program opět správné hodnoty.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="jak-to-vypadá-v-praxi">Jak to vypadá v praxi<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#jak-to-vypad%C3%A1-v-praxi" class="hash-link" aria-label="Přímý odkaz na Jak to vypadá v praxi" title="Přímý odkaz na Jak to vypadá v praxi" translate="no">​</a></h2>
<p>Několik příznaků a co za nimi obvykle stojí:</p>





























<table><thead><tr><th>Příznak</th><th>Pravděpodobná příčina</th></tr></thead><tbody><tr><td>Program skončí ve HardFault hned po resetu</td><td>První slovo vektorové tabulky není platná adresa zásobníku (špatné <code>_estack</code>, špatná velikost RAM), nebo tabulka není na začátku flash</td></tr><tr><td>Globální proměnná s inicializátorem má špatnou hodnotu, ta s <code>= 0</code> také</td><td><code>.data</code> se nekopíruje nebo <code>.bss</code> se nenuluje (špatný symbol, sekce chybějící ve skriptu)</td></tr><tr><td>Po zapnutí napájení funguje, po resetu selže</td><td>Totéž, RAM byla při zapnutí náhodou prázdná</td></tr><tr><td>Podivná hodnota, která se mění s velikostí kódu</td><td>Zásobník roste dolů do <code>.bss</code> / <code>.data</code>, přetečení zásobníku</td></tr><tr><td>První <code>printf</code> nebo ovladač nefunguje</td><td>Kód, který běží před kroky 1 a 2, používá globální proměnnou</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-vám-říkají-čísla-z-nástroje">Co vám říkají čísla z nástroje<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#co-v%C3%A1m-%C5%99%C3%ADkaj%C3%AD-%C4%8D%C3%ADsla-z-n%C3%A1stroje" class="hash-link" aria-label="Přímý odkaz na Co vám říkají čísla z nástroje" title="Přímý odkaz na Co vám říkají čísla z nástroje" 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>. Počáteční hodnoty <code>.data</code> zabírají místo i ve flash, takže velké inicializované pole vás stojí dvojnásobek: ve flash i v RAM. Pole, které se nemění, by mělo být <code>const</code> a pak je jen ve flash.</li>
<li class=""><strong>RAM</strong> = <code>data</code> + <code>bss</code> (+ zásobník a halda).</li>
</ul>
<p>Zkontrolovat to za vás umí i linker: <code>-Wl,--print-memory-usage</code> vypíše, kolik z každé oblasti je využito:</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>Zařaďte tento přepínač do buildu a když je něco na neočekávaném místě, přečtěte si soubor <code>.map</code> (<code>-Wl,-Map,out.map</code>): obsahuje adresu každé funkce a každé proměnné.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shrnutí">Shrnutí<a href="https://embedbits.cz/cs/blog/before-main-startup-linker#shrnut%C3%AD" class="hash-link" aria-label="Přímý odkaz na Shrnutí" title="Přímý odkaz na Shrnutí" translate="no">​</a></h2>
<ol>
<li class="">Po resetu jádro přečte dvě slova: ukazatel zásobníku a adresu reset handleru. Vše ostatní je váš kód.</li>
<li class=""><strong>Linker script</strong> je mapa: kde jsou paměti, v jakém pořadí leží sekce a které symboly označují jejich hranice.</li>
<li class=""><strong>Startup kód</strong> je to, co činí slibované vlastnosti jazyka pravdivými: kopíruje <code>.data</code>, nuluje <code>.bss</code>, spouští konstruktory a volá <code>main()</code>.</li>
<li class="">Proměnná, která má hodnotu ve flash a žije v RAM, má dvě adresy, load address a run address. To je klíč k celému tématu.</li>
<li class="">Nechte zapnuté <code>-Wl,--print-memory-usage</code> a čtěte <code>arm-none-eabi-size</code> a map soubor. Řeknou vám o tom, kam se poděla vaše paměť, víc než debugger.</li>
</ol>
<p>V Embedbits BSP tyto dva soubory sami nepíšete: linker script se generuje pro vybrané MCU a startup kód přichází s větví BSP pro danou rodinu. Přesto stojí za to pochopit, co dělají, protože když firmware nenastartuje, nikdo jiný vám nepomůže.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>STM32</category>
        </item>
        <item>
            <title><![CDATA[Unit testování embedded C na PC pomocí Unity a CMock]]></title>
            <link>https://embedbits.cz/cs/blog/unit-testing-unity-cmock</link>
            <guid>https://embedbits.cz/cs/blog/unit-testing-unity-cmock</guid>
            <pubDate>Mon, 05 Oct 2026 10:00:00 GMT</pubDate>
            <description><![CDATA[„Embedded software se nedá unit testovat, potřebujete hardware." Slýchám to často a platí to přesně pro jeden druh kódu: kód, který sahá na registry. Všechno ostatní, stavové automaty, parsery protokolů, řídicí logika, převody hodnot, je obyčejné C, které se přeloží na vašem PC. A na PC běží v milisekundách, bez debuggeru, bez kabelu a bez flashování.]]></description>
            <content:encoded><![CDATA[<p>„Embedded software se nedá unit testovat, potřebujete hardware." Slýchám to často a platí to přesně pro jeden druh kódu: kód, který sahá na registry. Všechno ostatní, stavové automaty, parsery protokolů, řídicí logika, převody hodnot, je obyčejné C, které se přeloží na vašem PC. A na PC běží v milisekundách, bez debuggeru, bez kabelu a bez flashování.</p>
<p>Tento článek ukazuje, jak otestovat modul pomocí <a href="https://github.com/ThrowTheSwitch/Unity" target="_blank" rel="noopener noreferrer" class="">Unity</a> (testovací framework) a <a href="https://github.com/ThrowTheSwitch/CMock" target="_blank" rel="noopener noreferrer" class="">CMock</a> (generátor mocků), od návrhu, který to umožňuje, až po soubor CMake, který to sestaví. Všechno bylo sestaveno a spuštěno a výstupy níže jsou skutečné.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-potřebujete-otestovat-a-co-musíte-odstranit">Co potřebujete otestovat a co musíte odstranit<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#co-pot%C5%99ebujete-otestovat-a-co-mus%C3%ADte-odstranit" class="hash-link" aria-label="Přímý odkaz na Co potřebujete otestovat a co musíte odstranit" title="Přímý odkaz na Co potřebujete otestovat a co musíte odstranit" translate="no">​</a></h2>
<p>Unit test spouští jeden modul izolovaně. Testovaný modul volá nižší vrstvu (BSP, ovladač, jiný modul) a <strong>to</strong> je problém: nižší vrstva potřebuje hardware. Řešením není dát modulu simulovaný hardware, ale nahradit celou nižší vrstvu něčím, co test ovládá. Tím něčím je <strong>mock</strong>: funkce se stejnou signaturou jako ta skutečná, která nedělá nic skutečného. Jen si pamatuje, jak byla zavolána, a vrací to, co jí test řekl, aby vrátila.</p>
<p>Funguje to jen tehdy, když má modul místo, kde lze nižší vrstvu nahradit. V článku o <a class="" href="https://embedbits.cz/cs/blog/solid-principles-c-cpp">principech SOLID</a> to bylo <em>link-time injection</em>: modul volá funkci deklarovanou v hlavičkovém souboru (<code>Bsp_Thermostat.h</code>) a build systém rozhoduje, který zdrojový soubor ji implementuje. Na cílovém zařízení je to skutečné BSP, v unit testu je to mock. Je to stejný princip jako u architektury z článku o <a class="" href="https://embedbits.cz/cs/blog/design-architecture">návrhu a architektuře</a>: když mají vrstvy čistá rozhraní, lze každou vrstvu testovat bez vrstev pod ní.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="nástroje">Nástroje<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#n%C3%A1stroje" class="hash-link" aria-label="Přímý odkaz na Nástroje" title="Přímý odkaz na Nástroje" translate="no">​</a></h2>
<ul>
<li class=""><strong>Unity</strong> je framework s asercemi (<code>TEST_ASSERT_TRUE</code>, <code>TEST_ASSERT_EQUAL_UINT8</code>, <code>TEST_ASSERT_EQUAL_FLOAT</code>, <code>TEST_ASSERT_EQUAL_MEMORY</code> a mnoho dalších) a malý skript, který z vašeho testovacího souboru vygeneruje <code>main()</code> se seznamem testů, takže nikdy nemusíte test registrovat ručně. Je to pár souborů C, které se překládají spolu s testem.</li>
<li class=""><strong>CMock</strong> přečte hlavičkový soubor a vygeneruje mock každé funkce v něm: <code>MockBsp_Thermostat.c/.h</code>. Je napsán v Ruby, ale jen <em>generátor</em>, vygenerovaný mock je obyčejné C.</li>
<li class=""><strong>Ruby</strong> je potřeba pro oba generátory, které běží při buildu. V testovaném kódu se neobjeví.</li>
</ul>
<p>V platformě Embedbits jsou tyto tři věci artefakty (<code>unity</code>, <code>cmock</code> a <code>ruby</code>), takže projekt nezávisí na tom, co má vývojář nainstalováno na PC. Verze jsou v <code>ArtifactsConfig.txt</code> (syntaxe je <code>&lt;artifact_name&gt;;&lt;binary_version&gt;;&lt;handler_version&gt;</code>). V tomto článku jsem použil Unity 2.6.1 a CMock 2.6.0 s čistým CMake, aby příklad fungoval všude.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="testovaný-modul">Testovaný modul<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#testovan%C3%BD-modul" class="hash-link" aria-label="Přímý odkaz na Testovaný modul" title="Přímý odkaz na Testovaný modul" translate="no">​</a></h2>
<p>Termostat s hysterezí. Čte teplotu z BSP, pod 20 °C zapne topení a nad 22 °C ho vypne. Pokud senzor neodpovídá, topení vypne, protože topení bez měření je požár. Rozhraní k hardwaru je hlavičkový soubor se dvěma funkcemi:</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>Veřejný port modulu a jeho implementace:</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>Modul neincluduje žádnou hardwarovou hlavičku, nezná STM32 a lze ho přeložit překladačem na vašem PC. To je první zkouška návrhu: když se nepřeloží, není dostatečně oddělený.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="test">Test<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#test" class="hash-link" aria-label="Přímý odkaz na Test" title="Přímý odkaz na Test" translate="no">​</a></h2>
<p>Testovací soubor includuje hlavičku testovaného modulu a hlavičku <strong>mocku</strong>, který zatím neexistuje. Vygeneruje se z <code>Bsp_Thermostat.h</code> během buildu.</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>Přečtěme si to odshora.</p>
<ul>
<li class=""><code>setUp()</code> volá Unity před každým testem. Modul drží svůj stav ve <code>static</code> proměnné, takže každý test začíná <code>Thermostat_Init()</code> a <code>Bsp_Set_Heater_Expect(false)</code> říká mocku, že inicializace topení vypíná. Bez tohoto resetu by testy závisely jeden na druhém a na svém pořadí.</li>
<li class=""><code>Sensor_Returns()</code> je pomocná funkce, která říká „příští volání <code>Bsp_Get_Celsius()</code> vrátí <code>true</code> a nastaví hodnotu na tuto teplotu". <code>_ExpectAnyArgsAndReturn</code> znamená „ukazatel mě nezajímá" a <code>_ReturnThruPtr_celsius</code> naplní výstupní parametr.</li>
<li class="">Každý test je krátký příběh o třech částech: senzor něco řekne, modul se spustí (<code>Thermostat_Task()</code>), výsledek se zkontroluje. Očekávání <code>Bsp_Set_Heater_Expect(true)</code> je také aserce: pokud modul zavolá funkci s jinou hodnotou, nebo ji nezavolá, test selže.</li>
<li class="">Třetí test ukazuje sílu mocků. Uvnitř pásma hystereze se nečeká nic, a to je ta aserce: mock test shodí, jakmile modul zavolá <code>Bsp_Set_Heater()</code>.</li>
</ul>
<p>Past, kterou stojí za to znát: <code>_ReturnThruPtr_celsius(&amp;value)</code> nekopíruje hodnotu v okamžiku volání, zapamatuje si <strong>ukazatel</strong> a hodnotu přečte, až modul mock zavolá. Pokud je <code>value</code> lokální proměnná pomocné funkce, už v té chvíli neexistuje. První verze příkladu pro tento článek měla pomocnou funkci napsanou právě takto a výsledkem byly čtyři neúspěšné testy se zprávou, která vypadá jako chyba v modulu:</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>Modul byl v pořádku, proměnná byla smetí. Proto má příklad <code>static float sensorCelsius</code> s komentářem.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="build">Build<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#build" class="hash-link" aria-label="Přímý odkaz na Build" title="Přímý odkaz na Build" translate="no">​</a></h2>
<p>Dva generátory a jeden spustitelný soubor. CMake spouští generátory před překladem a změna hlavičky mock znovu vygeneruje:</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>Konfigurace CMocku (<code>cmock.yml</code>) obsahuje jen seznam pluginů: <code>ignore</code>, <code>expect_any_args</code> a <code>return_thru_ptr</code>, které dávají funkce <code>_Ignore</code>, <code>_ExpectAnyArgs</code> a <code>_ReturnThruPtr_</code>, jež test výše používá. Cesta <code>mock_path</code> je relativní ke složce, ve které generátor běží, tedy k build adresáři.</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>Všimněte si, co ve spustitelném souboru <em>není</em>: žádný startup kód, žádný linker script, žádné HAL, žádná hlavička od ST. Jen modul, mock, test a framework. Sestaví se za pár sekund a běží v milisekundách, takže se může spouštět při každém uložení a při každém commitu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="testuje-test-opravdu-něco">Testuje test opravdu něco?<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#testuje-test-opravdu-n%C4%9Bco" class="hash-link" aria-label="Přímý odkaz na Testuje test opravdu něco?" title="Přímý odkaz na Testuje test opravdu něco?" translate="no">​</a></h2>
<p>Test, který nemůže selhat, nemá žádnou cenu. Nejlevnější kontrolou je <strong>mutace</strong>: kód záměrně rozbijte a podívejte se, jestli si toho některý test všimne. Změnil jsem horní mez z 22 °C na 20 °C, čímž hystereze zmizí:</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>Test hystereze chybu zachytil a zpráva říká, co se stalo: modul zavolal <code>Bsp_Set_Heater()</code>, když neměl. Je dobrým zvykem udělat to jednou pro každý nový test.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-mockovat-a-co-ne">Co mockovat a co ne<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#co-mockovat-a-co-ne" class="hash-link" aria-label="Přímý odkaz na Co mockovat a co ne" title="Přímý odkaz na Co mockovat a co ne" translate="no">​</a></h2>
<ul>
<li class=""><strong>Mockujte hranici modulu, ne jeho vnitřek.</strong> Mock nahrazuje rozhraní nižší vrstvy (zde <code>Bsp_Thermostat.h</code>). Nemockujte vlastní pomocné funkce ve stejném modulu: test pak popisuje, jak je kód napsán, a rozbije se při každém refaktoringu, i když je chování stejné.</li>
<li class=""><strong>Testujte přes veřejný port.</strong> Test includuje <code>Thermostat_Port.h</code> a nic dalšího z modulu. Pokud potřebujete interní hlavičku, abyste něco otestovali, je to znamení, že modul má dvě odpovědnosti. Jak se oddělují veřejné a interní soubory, si přečtěte v článku o <a class="" href="https://embedbits.cz/cs/blog/file-organization-embedded-c">organizaci souborů</a>.</li>
<li class=""><strong>Jedno chování, jeden test.</strong> Název říká, co se očekává (<code>HeaterSwitchesOffWhenSensorFails</code>), takže červený test vám řekne, co je rozbité, dřív než ho otevřete.</li>
<li class=""><strong>Stejný vzor funguje v každé vrstvě.</strong> Modul aplikace se testuje s mockem rozhraní BSP, modul MCAL s mockem portu RAL. V každém případě je vrstva pod ním nahrazena a testovaná vrstva je skutečná.</li>
<li class=""><strong>Pořadí volání.</strong> CMock umí zkontrolovat, že volání různých mocků proběhnou v daném pořadí (volba <code>:enforce_strict_ordering</code>). Hodí se to pro inicializační sekvence, ale používejte to jen tam, kde je pořadí požadavkem, a ne náhodou implementace.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-vám-host-test-neřekne">Co vám host test neřekne<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#co-v%C3%A1m-host-test-ne%C5%99ekne" class="hash-link" aria-label="Přímý odkaz na Co vám host test neřekne" title="Přímý odkaz na Co vám host test neřekne" translate="no">​</a></h2>
<p>Nechci prodávat host testy jako všelék. Nenajdou:</p>
<ul>
<li class=""><strong>časování</strong>, přerušení a race conditions mezi nimi,</li>
<li class=""><strong>registry</strong>: že pin opravdu přejde do high, že byly zapnuty hodiny periferie. To je práce kódu v RAL a MCAL a vyžaduje to simulátor nebo skutečný hardware,</li>
<li class=""><strong>rozdíly mezi PC a MCU</strong>: šířku <code>int</code>, zarovnání, optimalizátor cílového překladače. Testy na PC ukazují, že logika je správně, ne že je správně firmware.</li>
</ul>
<p>Proto jsou host testy základnou pyramidy: je jich mnoho, jsou rychlé a běží při každém commitu. Nad nimi je simulátor (například Renode) a hardwarové testy, kterých je méně, jsou pomalejší a pokrývají to, co PC nedokáže.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shrnutí">Shrnutí<a href="https://embedbits.cz/cs/blog/unit-testing-unity-cmock#shrnut%C3%AD" class="hash-link" aria-label="Přímý odkaz na Shrnutí" title="Přímý odkaz na Shrnutí" translate="no">​</a></h2>
<ol>
<li class="">Navrhněte modul tak, aby vše pod ním bylo za hlavičkovým souborem (tzv. <em>seam</em>).</li>
<li class="">Nechte CMock vygenerovat mock z této hlavičky a Unity runner z testovacího souboru.</li>
<li class="">Sestavte jeden malý spustitelný soubor pro PC: modul, mock, test, framework.</li>
<li class="">Pište testy jako příběhy: mock říká, jak svět vypadá, modul jedná, aserce zkontroluje výsledek.</li>
<li class="">Jednou kód záměrně rozbijte, abyste viděli, že test selže.</li>
</ol>
<p>Celý příklad má asi 150 řádků kódu a až se vás příště někdo zeptá, jestli termostat opravdu vypne topení, když selže senzor, nepotřebujete topení. Spustíte <code>ctest</code>.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>Testování</category>
        </item>
        <item>
            <title><![CDATA[Organizace souborů v embedded C: jak se ze složky stane modul]]></title>
            <link>https://embedbits.cz/cs/blog/file-organization-embedded-c</link>
            <guid>https://embedbits.cz/cs/blog/file-organization-embedded-c</guid>
            <pubDate>Sun, 04 Oct 2026 14:00:00 GMT</pubDate>
            <description><![CDATA[Můj coding style říká, že názvy souborů začínají názvem modulu a že „kompletní organizace souborů je popsána jinde". Tohle je to „jinde".]]></description>
            <content:encoded><![CDATA[<p>Můj <a class="" href="https://embedbits.cz/cs/docs/platform/embi-platform/coding-style">coding style</a> říká, že názvy souborů začínají názvem modulu a že „kompletní organizace souborů je popsána jinde". Tohle je to „jinde".</p>
<p>C nemá <code>private</code>, jmenné prostory ani balíčky. Jakmile je kód rozdělen do souborů, jsou soubory a build systém <strong>jedinými</strong> nástroji, kterými můžete říct, co k sobě patří, co je veřejné a co se nikoho jiného netýká. Organizace souborů tedy není věcí vkusu, je součástí návrhu. Tento článek popisuje, jak organizuji embedded projekt na třech úrovních: projekt, modul a jednotlivý soubor.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="úroveň-1-projekt">Úroveň 1: projekt<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#%C3%BArove%C5%88-1-projekt" class="hash-link" aria-label="Přímý odkaz na Úroveň 1: projekt" title="Přímý odkaz na Úroveň 1: projekt" translate="no">​</a></h2>
<p>Projekt vytvořený pomocí EmBi_Platform má pokaždé stejné uspořádání:</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>Každá složka odpovídá na jednu otázku a odpověď je důvodem, proč tam kód leží.</p>
<p><strong>Application</strong> je to, čím se produkt liší od každého jiného produktu na stejném MCU. Má vlastní vnitřní vrstvy a jejich názvy jsou úrovně „stromu" z <a class="" href="https://embedbits.cz/cs/blog/design-architecture">článku o architektuře</a>: <code>AppMain</code> vše spouští, <code>AppCore</code> je vrchol stromu s logikou celého zařízení, <code>AppFun</code> obsahuje jednotlivé funkcionality, <code>AppComp</code> nízkoúrovňové komponenty, ze kterých jsou postaveny, a <code>AppCom</code> komunikaci s vnějším světem. Volání jdou shora dolů, nikdy opačně.</p>
<p><strong>Middlewares</strong> mají pro každou komponentu dvě místa, a to záměrně. <code>ThirdParty/FreeRTOS</code> je kód od výrobce, stažený jako Git submodul ve verzi, kterou si zvolíte, a <strong>nikdy ho neupravujete</strong>. Vše, co je vaše (port layer, konfigurace), leží vedle něj v <code>Middlewares/FreeRTOS</code> a nepřepíše se, když kód výrobce přepnete na jinou verzi. Když výrobce vydá opravu, aktualizujete submodul, a ne záplatovanou kopii.</p>
<p><strong>Bsp</strong> je popsán v <a class="" href="https://embedbits.cz/cs/docs/bsp">dokumentaci BSP</a>, stručná verze zní: <code>Ral</code> zná registry, <code>Mcal</code> periferie a <code>Hal</code> desku. Každá rodina STM32 má vlastní větev BSP, takže složky vypadají pro každé MCU stejně.</p>
<p><strong>EmBi_Platform</strong> a <strong>STM32CubeIDE</strong> jsou nástroje. Do binárního souboru se nedostanou a projekt IDE je generovaný, takže ho lze zahodit a vytvořit znovu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="úroveň-2-modul">Úroveň 2: modul<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#%C3%BArove%C5%88-2-modul" class="hash-link" aria-label="Přímý odkaz na Úroveň 2: modul" title="Přímý odkaz na Úroveň 2: modul" translate="no">​</a></h2>
<p>Modul je složka s pevnou sadou souborů. Nemusíte je vytvářet ručně, generuje je platforma (viz konec článku) a výsledek vypadá takto:</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>Soubor</th><th>Role</th><th>Kdo ho smí includovat</th></tr></thead><tbody><tr><td><code>Temperature_Types.h</code></td><td>Veřejné typy, výčty a makra</td><td>kdokoli</td></tr><tr><td><code>Temperature_Port.h</code></td><td>Veřejné funkce: <strong>jediný</strong> vstupní bod modulu</td><td>kdokoli</td></tr><tr><td><code>Temperature.h</code></td><td>Interní typy a funkce sdílené soubory modulu</td><td>pouze modul sám</td></tr><tr><td><code>Temperature.c</code></td><td>Implementace</td><td>(zdrojový soubor)</td></tr><tr><td><code>CMakeLists.txt</code></td><td>Vytváří statickou knihovnu <code>Temperature_Lib</code></td><td>build</td></tr></tbody></table>
<p>Myšlenka je, že uživatel modulu čte <strong>dva</strong> soubory a nic jiného. První jsou typy (generovaný soubor obsahuje také typ verze a obvyklé výčty pro stavy požadavku a funkce, zde jsem ho zkrátil na to, co příklad potřebuje):</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>Druhý je port, tedy celé rozhraní modulu. Co tu není, pro ostatní neexistuje:</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>Interní hlavičkový soubor obsahuje data a funkce, které soubory modulu potřebují sdílet a které by nikdo zvenčí neměl nikdy vidět:</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>A implementace to všechno využívá:</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>Všimněte si, že stav je <code>static</code> v souboru <code>.c</code>. Neexistuje žádná globální proměnná, takže není žádné <code>extern</code> (které můj coding style zakazuje). Jedinou cestou k datům je funkce <code>Temperature_Get_Value()</code>, getter, který volajícímu také sdělí, zda je hodnota platná.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="build-systém-dělá-ze-souboru-enkapsulaci">Build systém dělá ze souboru enkapsulaci<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#build-syst%C3%A9m-d%C4%9Bl%C3%A1-ze-souboru-enkapsulaci" class="hash-link" aria-label="Přímý odkaz na Build systém dělá ze souboru enkapsulaci" title="Přímý odkaz na Build systém dělá ze souboru enkapsulaci" translate="no">​</a></h3>
<p>„Includujte jen port" by bylo jen přání, kdyby to nic nevynucovalo. <code>CMakeLists.txt</code> každého modulu to vynucuje. Sestaví statickou knihovnu a <strong>zkopíruje jen veřejné hlavičky</strong> do samostatné složky v build adresáři. Tato složka je jediná, kterou uživatelé knihovny dostanou v include cestě:</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>(Toto je zjednodušená verze šablony, kterou platforma generuje; ta navíc řeší závislosti mezi knihovnami a cesty pro Doxygen.) Aplikace teď jen linkuje <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>Vyzkoušel jsem, co se stane, když aplikace includuje interní hlavičku modulu, a překladač řekne to, co chcete, aby řekl:</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>Složka s veřejnými hlavičkami v build adresáři obsahuje přesně dva soubory: <code>Temperature_Port.h</code> a <code>Temperature_Types.h</code>.</p>
<p><strong>Upřímné varování:</strong> je to ochrana build systému, ne jazyka. Pokud někdo napíše <code>#include "../../Middlewares/Temperature/Temperature.h"</code>, přeloží se to bez stížností (to jsem také vyzkoušel). Lék je levný: v CI zamítněte relativní cesty s <code>..</code> v includech.</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="když-modul-roste-komponenty">Když modul roste: komponenty<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#kdy%C5%BE-modul-roste-komponenty" class="hash-link" aria-label="Přímý odkaz na Když modul roste: komponenty" title="Přímý odkaz na Když modul roste: komponenty" translate="no">​</a></h3>
<p>Modul s tisícem řádků v jednom souboru je další problém. Odpovědí je <strong>komponenta</strong>: další dvojice souborů <code>Module_Component.c/.h</code> ve stejné složce. Ve výše uvedeném příkladu je to filtr:</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>Hlavička komponenty je také interní (není v seznamu veřejných hlaviček), takže komponentu lze vyměnit nebo rozdělit, aniž by si toho někdo všiml. Uživatel modulu stále vidí stejné dva soubory. Pravidlo, že název souboru začíná názvem modulu, dělá komponentu viditelnou v každém seznamu souborů a název funkce <code>Temperature_Filter_Apply()</code> říká, kde ji hledat.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="úroveň-3-uvnitř-souboru">Úroveň 3: uvnitř souboru<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#%C3%BArove%C5%88-3-uvnit%C5%99-souboru" class="hash-link" aria-label="Přímý odkaz na Úroveň 3: uvnitř souboru" title="Přímý odkaz na Úroveň 3: uvnitř souboru" translate="no">​</a></h2>
<p>Každý soubor <code>.c</code> a <code>.h</code> generovaný platformou má stejnou kostru s bannerem pro každou sekci, ve stejném pořadí:</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>Vypadá to jako dekorace, ale je to mapa. Když otevřete soubor, který jste nikdy neviděli, víte, že lokální proměnné jsou v páté sekci a obsluhy přerušení v desáté, a nemusíte soubor číst, abyste je našli. Hlavičky mají stejnou myšlenku, obalenou include guardem a <code>extern "C"</code> pro uživatele C++:</p>
<ul>
<li class="">guard má tvar <code>MODULE_FILE_H</code>, například <code>TEMPERATURE_TEMPERATURE_PORT_H</code>,</li>
<li class="">hlavička Doxygen (<code>\file</code>, <code>\ingroup</code>, <code>\brief</code>) je na začátku každého souboru, takže dokumentace modulu se generuje ze stejné složky,</li>
<li class="">includy jsou seřazeny <code>&lt;systémové&gt;</code>, potom projektové, potom modulové.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="jeden-název-na-všech-místech">Jeden název na všech místech<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#jeden-n%C3%A1zev-na-v%C5%A1ech-m%C3%ADstech" class="hash-link" aria-label="Přímý odkaz na Jeden název na všech místech" title="Přímý odkaz na Jeden název na všech místech" translate="no">​</a></h2>
<p>Síla této organizace je v tom, že název modulu je všude stejný, takže název můžete uhodnout, aniž byste ho museli hledat:</p>





































<table><thead><tr><th>Co</th><th>Příklad</th></tr></thead><tbody><tr><td>Složka</td><td><code>Temperature/</code></td></tr><tr><td>Knihovna v CMake</td><td><code>Temperature_Lib</code></td></tr><tr><td>Soubory</td><td><code>Temperature.c</code>, <code>Temperature_Port.h</code>, <code>Temperature_Types.h</code></td></tr><tr><td>Funkce</td><td><code>Temperature_Init()</code>, <code>Temperature_Get_Value()</code></td></tr><tr><td>Typy</td><td><code>temperature_Value_t</code>, <code>temperature_RequestState_t</code></td></tr><tr><td>Makra a enumerátory</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>Pokud ve stack trace uvidíte <code>Gpio_Set_PinLevel()</code>, víte, že je ve složce <code>Gpio</code>, v knihovně <code>Gpio_Lib</code> a že jeho typy začínají <code>gpio_</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="stejný-životní-cyklus-pro-každý-modul">Stejný životní cyklus pro každý modul<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#stejn%C3%BD-%C5%BEivotn%C3%AD-cyklus-pro-ka%C5%BEd%C3%BD-modul" class="hash-link" aria-label="Přímý odkaz na Stejný životní cyklus pro každý modul" title="Přímý odkaz na Stejný životní cyklus pro každý modul" translate="no">​</a></h3>
<p>Generovaný modul přichází se čtyřmi funkcemi, které má každý modul: <code>Get_ModuleVersion()</code>, <code>Init()</code>, <code>Deinit()</code> a <code>Task()</code>. <code>Init</code> modul nastaví a ošetří jeho vlastní selhání, <code>Task</code> se volá periodicky z hlavní smyčky nebo ze scheduleru. Důsledkem je, že kód nahoře (<code>AppMain</code>) může se všemi moduly zacházet stejně a nový modul nepotřebuje nový koncept.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vytvoření-modulu">Vytvoření modulu<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#vytvo%C5%99en%C3%AD-modulu" class="hash-link" aria-label="Přímý odkaz na Vytvoření modulu" title="Přímý odkaz na Vytvoření modulu" translate="no">​</a></h2>
<p>Tyto soubory nevytváříte ručně. Projektové nástroje platformy (položka menu <em>Create module</em>, popsaná na stránce <a class="" href="https://embedbits.cz/cs/docs/platform/embi-platform/cmake-helpertools">Project tools</a>) se zeptají na název a umístění a vygenerují složku se všemi výše uvedenými soubory a <code>CMakeLists.txt</code>. Položka <em>Add component</em> přidá dvojici <code>Module_Component.c/.h</code> do existujícího modulu. Jednou vygenerovaný modul se nikdy nepřepisuje, takže je bezpečné nástroj spustit znovu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pravidla-ve-stručné-podobě">Pravidla ve stručné podobě<a href="https://embedbits.cz/cs/blog/file-organization-embedded-c#pravidla-ve-stru%C4%8Dn%C3%A9-podob%C4%9B" class="hash-link" aria-label="Přímý odkaz na Pravidla ve stručné podobě" title="Přímý odkaz na Pravidla ve stručné podobě" translate="no">​</a></h2>
<ol>
<li class="">Jeden modul je jedna složka a má vlastní knihovnu.</li>
<li class="">Ostatní moduly includují <strong>pouze</strong> <code>Module_Port.h</code> a <code>Module_Types.h</code>.</li>
<li class="">Interní hlavičky nejsou v seznamu veřejných hlaviček.</li>
<li class="">Data jsou <code>static</code> v souboru <code>.c</code>, přístup vede přes funkce. Žádné proměnné <code>extern</code>.</li>
<li class="">Název souboru začíná názvem modulu, stejně tak každá funkce, typ a makro.</li>
<li class="">Kód výrobce se nikdy neupravuje. Vaše změny žijí ve složce handleru vedle něj.</li>
<li class="">Volání jdou ve vrstvách dolů, nikdy nahoru.</li>
<li class="">Vše v souboru je ve své sekci, ve stejném pořadí.</li>
</ol>
<p>Žádné z těchto pravidel není vychytralé. Podstatné je, že všechna jsou ve všech modulech stejná, takže poté, co přečtete jeden modul, víte, jak číst všechny ostatní. To je také důvod, proč platforma soubory generuje: konvence, jejíž dodržování dá práci, je konvence, která se nedodržuje.</p>
<p>Stejné myšlenky z jiného úhlu pohledu jsou v článcích o <a class="" href="https://embedbits.cz/cs/blog/solid-principles-c-cpp">principech SOLID</a> (port header je rozhraní, na kterém ostatní moduly závisejí) a o <a class="" href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice">MISRA C</a> (několik pravidel je mnohem snazší dodržet, když je kód takto organizován).</p>]]></content:encoded>
            <category>Embedded</category>
            <category>Architektura</category>
            <category>C</category>
        </item>
        <item>
            <title><![CDATA[Pravidla MISRA C v praxi: co jsou zač, proč existují a jak s nimi žít]]></title>
            <link>https://embedbits.cz/cs/blog/misra-c-rules-in-practice</link>
            <guid>https://embedbits.cz/cs/blog/misra-c-rules-in-practice</guid>
            <pubDate>Sun, 04 Oct 2026 10:00:00 GMT</pubDate>
            <description><![CDATA[Řekněte „MISRA“ v místnosti plné embedded vývojářů a polovina si povzdechne, zatímco druhá se zeptá, jaký nástroj používáte. Pověst těchto pravidel je rozporuplná: pro některé je to byrokracie, která před každým vydáním sežere týden, pro jiné důvod, proč se auto na dálnici nerestartuje. Obě skupiny mají zčásti pravdu.]]></description>
            <content:encoded><![CDATA[<p>Řekněte „MISRA“ v místnosti plné embedded vývojářů a polovina si povzdechne, zatímco druhá se zeptá, jaký nástroj používáte. Pověst těchto pravidel je rozporuplná: pro některé je to byrokracie, která před každým vydáním sežere týden, pro jiné důvod, proč se auto na dálnici nerestartuje. Obě skupiny mají zčásti pravdu.</p>
<p>V tomto článku projdu pravidla, se kterými se setkávám nejčastěji, jedno po druhém: co pravidlo požaduje, co za to získáte, jak vypadá špatný kód, jak vypadá dobrý kód a kdo za vás problém najde. Všechny příklady jsou skutečný C kód, který jsem přeložil a spustil.</p>
<!-- -->
<blockquote>
<p><strong>Poznámka k textům pravidel</strong></p>
<p>MISRA C je dokument chráněný autorskými právy konsorcia MISRA. Jeho znění zde nekopíruji. Každé pravidlo popisuji vlastními slovy a vlastními příklady, citována jsou pouze čísla a kategorie. Čísla se vztahují k normě <strong>MISRA C:2012</strong> (MISRA C:2023 shrnuje dodatky, ponechává tato čísla a přidává několik nových směrnic). Než na tomto článku postavíte cokoli důležitého, ověřte si pravidlo ve vlastním výtisku normy, který získáte na <a href="https://misra.org.uk/" target="_blank" rel="noopener noreferrer" class="">misra.org.uk</a>. Tento článek je nezávislý a MISRA ho neschvaluje.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-je-misra-c-a-co-není">Co je MISRA C (a co není)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#co-je-misra-c-a-co-nen%C3%AD" class="hash-link" aria-label="Přímý odkaz na Co je MISRA C (a co není)" title="Přímý odkaz na Co je MISRA C (a co není)" translate="no">​</a></h2>
<p>MISRA je zkratka pro <em>Motor Industry Software Reliability Association</em>. První směrnice pro jazyk C vyšly v roce 1998 pro automobilový průmysl, dnes se používají v letectví, na železnici, ve zdravotnických prostředcích a v průmyslové automatizaci, tedy v podstatě všude, kde selhání softwaru někomu ublíží.</p>
<p>Základní myšlenka je jednoduchá. C je jazyk, který dovoluje spoustu věcí, jež jsou legální, ale nebezpečné: nedefinované chování, chování definované implementací, implicitní konverze měnící hodnoty, ukazatele, které mohou mířit kamkoli. MISRA definuje <strong>podmnožinu jazyka C</strong>, ve které jsou nebezpečné části zakázané nebo je nutné je zdůvodnit. Není to jiný jazyk. Program vyhovující MISRA je pořád normální C program, který váš běžný překladač přeloží.</p>
<p>Čím MISRA <strong>není</strong>:</p>
<ul>
<li class="">Není to certifikace. „Vyhovuje MISRA“ je tvrzení, které sami vyslovíte a zdokumentujete, nikdo váš kód neopatří razítkem.</li>
<li class="">Není to záruka správnosti. Pravidla odstraňují třídy chyb, ale nekontrolují, že termostat opravdu reguluje teplotu.</li>
<li class="">Nejde o styl. Pojmenování, odsazení a organizace souborů nejsou součástí MISRA, od toho je <a class="" href="https://embedbits.cz/cs/docs/platform/embi-platform/coding-style">coding style</a>.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="jak-číst-pravidlo">Jak číst pravidlo<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#jak-%C4%8D%C3%ADst-pravidlo" class="hash-link" aria-label="Přímý odkaz na Jak číst pravidlo" title="Přímý odkaz na Jak číst pravidlo" translate="no">​</a></h3>
<p>Každá směrnice má tři vlastnosti, které byste měli znát dřív, než přečtete první z nich:</p>

























<table><thead><tr><th>Vlastnost</th><th>Hodnoty</th><th>Význam</th></tr></thead><tbody><tr><td><strong>Druh</strong></td><td><em>Directive</em> / <em>Rule</em></td><td>Pravidlo (rule) lze ověřit pouhým pohledem na zdrojový kód. Direktiva (directive) potřebuje další informace (návrh, proces), takže nástroj může pomoci, ale nemůže rozhodnout.</td></tr><tr><td><strong>Kategorie</strong></td><td><em>Mandatory</em> / <em>Required</em> / <em>Advisory</em></td><td>Mandatory: žádná výjimka. Required: výjimka je možná s písemným zdůvodněním. Advisory: doporučení, stačí zaznamenat, že se jím neřídíte.</td></tr><tr><td><strong>Rozhodnutelnost</strong></td><td><em>Decidable</em> / <em>Undecidable</em></td><td>Zda nástroj dokáže dát přesnou odpověď. U nerozhodnutelných pravidel i nejlepší analyzátor produkuje falešné poplachy nebo něco přehlédne.</td></tr></tbody></table>
<p>Číslování je <code>Dir 4.12</code> pro direktivy a <code>Rule 9.1</code> pro pravidla, kde první číslo označuje téma (9 = inicializace, 10 = typy, 11 = ukazatele, ...).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pravidla-jedno-po-druhém">Pravidla jedno po druhém<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#pravidla-jedno-po-druh%C3%A9m" class="hash-link" aria-label="Přímý odkaz na Pravidla jedno po druhém" title="Přímý odkaz na Pravidla jedno po druhém" translate="no">​</a></h2>
<p>Seskupil jsem je podle problému, který řeší, ne podle čísla.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pravidla-o-hodnotách-které-nejsou-takové-jak-si-myslíte">Pravidla o hodnotách, které nejsou takové, jak si myslíte<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#pravidla-o-hodnot%C3%A1ch-kter%C3%A9-nejsou-takov%C3%A9-jak-si-mysl%C3%ADte" class="hash-link" aria-label="Přímý odkaz na Pravidla o hodnotách, které nejsou takové, jak si myslíte" title="Přímý odkaz na Pravidla o hodnotách, které nejsou takové, jak si myslíte" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-91---čti-až-po-zápisu-mandatory">Rule 9.1 - čti až po zápisu (Mandatory)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-91---%C4%8Dti-a%C5%BE-po-z%C3%A1pisu-mandatory" class="hash-link" aria-label="Přímý odkaz na Rule 9.1 - čti až po zápisu (Mandatory)" title="Přímý odkaz na Rule 9.1 - čti až po zápisu (Mandatory)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> nečtěte proměnnou s automatickou dobou trvání dřív, než jí byla přiřazena hodnota.</p>
<p><strong>Co za to získáte:</strong> hodnota takové proměnné je smetí a na jiném překladači nebo s jinou úrovní optimalizace je to <em>jiné</em> smetí. Chyby typu „v debugu funguje, v release selhává“ končí velmi často právě tady. Protože je pravidlo mandatory, výjimka není možná.</p>
<p>Špatně, proměnná se nastaví jen na jedné cestě:</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>Dobře, každá cesta má definovanou hodnotu:</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>Kdo to najde:</strong> překladač občas (<code>-Wall -Wmaybe-uninitialized</code> s optimalizací), statický analyzátor spolehlivě. V mém testovacím buildu gcc u této funkce mlčel. Nespoléhejte na něj.</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/cs/blog/misra-c-rules-in-practice#rules-101-103-104---essential-types-required" class="hash-link" aria-label="Přímý odkaz na Rules 10.1, 10.3, 10.4 - essential types (Required)" title="Přímý odkaz na Rules 10.1, 10.3, 10.4 - essential types (Required)" translate="no">​</a></h4>
<p><strong>Pravidla:</strong> autoři MISRA vymysleli <em>model essential types</em>: typ, který výraz <em>vypadá, že má</em> (<code>uint8_t</code> zůstává z jejich pohledu „unsigned 8 bit“), na rozdíl od typu, který C potichu používá (<code>int</code>, kvůli integer promotion). Pravidla zakazují operace mezi nevhodnými typy, přiřazení hodnoty do užšího typu a míchání kategorií (signed, unsigned, boolean, character, floating).</p>
<p><strong>Co za to získáte:</strong> integer promotions jsou největším zdrojem překvapení v embedded C. Všechny hodnoty menší než <code>int</code> se před jakoukoli aritmetikou povýší na <code>int</code> a vy to nevidíte. Dva klasické výsledky:</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> není 8bitová hodnota, ale <code>int</code> s hodnotou <code>0xFFFFFFF0</code>. Porovnání nikdy neuspěje, ať je argument jakýkoli. Řešením je říct, co myslíte:</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>Druhým klasikem je tiché zúžení:</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> se spočítá jako <code>int</code> (300) a přiřazení do <code>uint8_t</code> zachová jen 44. Žádné varování, žádná chyba, špatný součet. Dvě správné varianty: rozšířit výsledek, nebo přetypovat záměrně a promyslet přetečení.</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>Kdo to najde:</strong> dobrý statický analyzátor. Překladač pomůže jen částečně: <code>-Wsign-compare</code> (součást <code>-Wextra</code>) ohlásil první příklad, zatímco u druhého gcc mlčel.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="directive-46---typy-s-velikostí-a-znaménkovostí-advisory">Directive 4.6 - typy s velikostí a znaménkovostí (Advisory)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#directive-46---typy-s-velikost%C3%AD-a-znam%C3%A9nkovost%C3%AD-advisory" class="hash-link" aria-label="Přímý odkaz na Directive 4.6 - typy s velikostí a znaménkovostí (Advisory)" title="Přímý odkaz na Directive 4.6 - typy s velikostí a znaménkovostí (Advisory)" translate="no">​</a></h4>
<p><strong>Direktiva:</strong> místo <code>char</code>, <code>short</code>, <code>int</code> a <code>long</code> používejte typedefy, které říkají velikost a znaménkovost (<code>uint8_t</code>, <code>int32_t</code> nebo vlastní názvy).</p>
<p><strong>Co za to získáte:</strong> šířka <code>int</code> závisí na překladači a MCU: 16 bitů na malých 8bitových a 16bitových řadičích, 32 bitů na Cortex-M. Kód, který funguje na jednom cíli, se na jiném potichu změní. S typy pevné šířky je ve zdrojovém kódu vidět, co kód dělá. Ve svých projektech jdu o krok dál a vytvářím vlastní názvy typů pro fyzikální veličiny (<code>temperature_t</code>, <code>humidity_t</code>), aby mě překladač zastavil, když je promíchám.</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---žádné-nedefinované-chování-required">Rule 1.3 - žádné nedefinované chování (Required)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-13---%C5%BE%C3%A1dn%C3%A9-nedefinovan%C3%A9-chov%C3%A1n%C3%AD-required" class="hash-link" aria-label="Přímý odkaz na Rule 1.3 - žádné nedefinované chování (Required)" title="Přímý odkaz na Rule 1.3 - žádné nedefinované chování (Required)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> program nesmí obsahovat nedefinované chování. To zahrnuje přetečení se znaménkem, posuny o příliš mnoho bitů, dělení nulou, použití visícího ukazatele a mnoho dalšího.</p>
<p><strong>Co za to získáte:</strong> při nedefinovaném chování může překladač udělat <em>cokoli</em>, včetně odstranění vaší bezpečnostní kontroly, protože „tento případ nemůže nastat“. Nejznámějším příkladem je přetečení se znaménkem: <code>first + second</code> na <code>int32_t</code>, které se nevejde, není „přetečení dokola“, ale licence pro optimalizátor.</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>Správný kód ověří podmínku <em>před</em> operací a nahlásí problém volajícímu:</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>Totéž platí pro posuny. Maska bitové pozice je definovaná jen tehdy, je-li pozice menší než šířka typu:</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>Kdo to najde:</strong> částečně překladač (<code>-fsanitize=undefined</code> to za běhu najde během testů), částečně analyzátor. Pravidlo je obecně nerozhodnutelné: nástroj vám může ukázat všechna místa, která by mohla být problém.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pravidla-o-podmínkách-a-řízení-toku">Pravidla o podmínkách a řízení toku<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#pravidla-o-podm%C3%ADnk%C3%A1ch-a-%C5%99%C3%ADzen%C3%AD-toku" class="hash-link" aria-label="Přímý odkaz na Pravidla o podmínkách a řízení toku" title="Přímý odkaz na Pravidla o podmínkách a řízení toku" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-144---řídicí-výraz-je-boolean-required">Rule 14.4 - řídicí výraz je boolean (Required)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-144---%C5%99%C3%ADdic%C3%AD-v%C3%BDraz-je-boolean-required" class="hash-link" aria-label="Přímý odkaz na Rule 14.4 - řídicí výraz je boolean (Required)" title="Přímý odkaz na Rule 14.4 - řídicí výraz je boolean (Required)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> podmínka v <code>if</code>, <code>while</code> a <code>for</code> musí být výraz s essential typem Boolean, tedy výsledek porovnání nebo <code>bool</code>. Samotné celé číslo nebo ukazatel nejsou povoleny.</p>
<p><strong>Co za to získáte:</strong> záměr je čitelný. <code>while (count)</code> neříká, zda chcete „dokud to není nula“, nebo „dokud to není konec“. Explicitní tvar vypadá stejně pro čísla, ukazatele i příznaky. (Konstantu píšu vlevo, <code>0u != count</code>, takže překlep s jedním <code>=</code> se nepřeloží.)</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>Kdo to najde:</strong> každý analyzátor MISRA, jde o rozhodnutelné pravidlo.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-121---zviditelněte-prioritu-operátorů-advisory">Rule 12.1 - zviditelněte prioritu operátorů (Advisory)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-121---zviditeln%C4%9Bte-prioritu-oper%C3%A1tor%C5%AF-advisory" class="hash-link" aria-label="Přímý odkaz na Rule 12.1 - zviditelněte prioritu operátorů (Advisory)" title="Přímý odkaz na Rule 12.1 - zviditelněte prioritu operátorů (Advisory)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> nespoléhejte na to, že si čtenář (a vy sami) pamatuje tabulku priorit, používejte závorky.</p>
<p><strong>Co za to získáte:</strong> priorita <code>&amp;</code> a <code>==</code> je v C opačná, než čeká lidský mozek. Tuto chybu napsal každý aspoň jednou:</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> se vyhodnotí jako první a dá <code>1</code>, takže funkce testuje bit 0 a ne masku. Pro <code>0x01</code> vrátí <code>true</code> a pro <code>0x0C</code> <code>false</code>, přesně obráceně. Se závorkami chyba nemůže vzniknout:</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>Kdo to najde:</strong> překladač (<code>-Wparentheses</code> je součástí <code>-Wall</code>) i každý analyzátor.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-156-157-163-a-164---úplné-příkazy-required">Rules 15.6, 15.7, 16.3 a 16.4 - úplné příkazy (Required)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rules-156-157-163-a-164---%C3%BApln%C3%A9-p%C5%99%C3%ADkazy-required" class="hash-link" aria-label="Přímý odkaz na Rules 15.6, 15.7, 16.3 a 16.4 - úplné příkazy (Required)" title="Přímý odkaz na Rules 15.6, 15.7, 16.3 a 16.4 - úplné příkazy (Required)" translate="no">​</a></h4>
<p><strong>Pravidla:</strong></p>
<ul>
<li class="">15.6: tělo <code>if</code>, <code>else</code>, <code>for</code>, <code>while</code> je vždy blok ve složených závorkách,</li>
<li class="">15.7: každý řetězec <code>if ... else if</code> končí větví <code>else</code>,</li>
<li class="">16.3: každá klauzule <code>switch</code> končí příkazem <code>break</code> (nebo jiným nepodmíněným skokem),</li>
<li class="">16.4: každý <code>switch</code> má <code>default</code>.</li>
</ul>
<p><strong>Co za to získáte:</strong> pravidla vás nutí odpovědět na otázku „co se stane ve všech ostatních případech?“ ve chvíli, kdy kód píšete, a ne v provozu. <code>switch</code> bez <code>break</code> je klasická chyba, <code>enum</code>, který dostane novou hodnotu, bez <code>default</code> je druhá. Složené závorky odstraňují celou rodinu chyb, kdy se pod <code>if</code> přidá druhý příkaz, který vypadá, jako by byl podmíněný:</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>A tady je switch. První verze propadne z <code>MODE_ON</code> do <code>MODE_ERROR</code> a nastaví špatnou hodnotu, druhá ošetří každý případ explicitně:</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>V mém testu gcc našel chybějící <code>default</code> i propadnutí (<code>-Wswitch-default -Wimplicit-fallthrough</code>). Pravidlo o <code>else</code> a složené závorky kontroluje analyzátor nebo formátovač.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-172---žádná-rekurze-required">Rule 17.2 - žádná rekurze (Required)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-172---%C5%BE%C3%A1dn%C3%A1-rekurze-required" class="hash-link" aria-label="Přímý odkaz na Rule 17.2 - žádná rekurze (Required)" title="Přímý odkaz na Rule 17.2 - žádná rekurze (Required)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> funkce nesmí volat sama sebe, ani přímo, ani přes jiné funkce.</p>
<p><strong>Co za to získáte:</strong> na PC má zásobník megabajty. Na mikrokontroléru máte pár kilobajtů a nejhorší případ hloubky rekurze závisí na vstupních datech. Pokud rekurzi odstraníte, maximální využití zásobníku lze <em>spočítat</em> (stačí statická analýza stromu volání) a přetečení zásobníku přestane být překvapením.</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>Iterativní verze potřebuje konstantní množství zásobníku:</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>Kdo to najde:</strong> analyzátor a linker map (některé toolchainy vypisují graf volání, <code>-fstack-usage</code> říká velikost každého rámce).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pravidla-o-paměti-a-ukazatelích">Pravidla o paměti a ukazatelích<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#pravidla-o-pam%C4%9Bti-a-ukazatel%C3%ADch" class="hash-link" aria-label="Přímý odkaz na Pravidla o paměti a ukazatelích" title="Přímý odkaz na Pravidla o paměti a ukazatelích" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="directive-412-a-rule-213---žádná-dynamická-paměť-required">Directive 4.12 a Rule 21.3 - žádná dynamická paměť (Required)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#directive-412-a-rule-213---%C5%BE%C3%A1dn%C3%A1-dynamick%C3%A1-pam%C4%9B%C5%A5-required" class="hash-link" aria-label="Přímý odkaz na Directive 4.12 a Rule 21.3 - žádná dynamická paměť (Required)" title="Přímý odkaz na Directive 4.12 a Rule 21.3 - žádná dynamická paměť (Required)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> nepoužívejte <code>malloc</code>, <code>calloc</code>, <code>realloc</code> a <code>free</code>.</p>
<p><strong>Co za to získáte:</strong></p>
<ul>
<li class="">halda se <em>fragmentuje</em>. Po týdnech běhu může selhat požadavek na 64 bajtů, přestože je volných 10 kB, jen ne v jednom kuse,</li>
<li class="">doba provádění <code>malloc</code> není deterministická,</li>
<li class="">únik paměti po týdnech běhu je nejhorší druh chyby k hledání,</li>
<li class="">spotřeba paměti je známá při linkování, ne ve 3 ráno v provozu.</li>
</ul>
<p>Standardní alternativou je pool s pevnou velikostí, který má stejný tvar API jako alokátor:</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>Funkce vrací <code>NULL</code>, jsou-li všechny rámce obsazené, takže případ „není paměť“ je v kódu ošetřen a dá se otestovat na PC. Úplně totéž se děje s <code>malloc</code>, jen to otestovat nemůžete, protože na vašem PC alokace nikdy neselže.</p>
<p><strong>Kdo to najde:</strong> analyzátor, nebo prostě linker, který <code>malloc</code> vůbec nelinkuje.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-113-a-115---opatrně-s-přetypováním-ukazatelů-required--advisory">Rules 11.3 a 11.5 - opatrně s přetypováním ukazatelů (Required / Advisory)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rules-113-a-115---opatrn%C4%9B-s-p%C5%99etypov%C3%A1n%C3%ADm-ukazatel%C5%AF-required--advisory" class="hash-link" aria-label="Přímý odkaz na Rules 11.3 a 11.5 - opatrně s přetypováním ukazatelů (Required / Advisory)" title="Přímý odkaz na Rules 11.3 a 11.5 - opatrně s přetypováním ukazatelů (Required / Advisory)" translate="no">​</a></h4>
<p><strong>Pravidla:</strong> nepřetypovávejte ukazatel na objekt jednoho typu na ukazatel na objekt jiného typu (11.3) a vyhněte se konverzi z <code>void *</code> na ukazatel na objekt (11.5).</p>
<p><strong>Co za to získáte:</strong> přetypování bajtového bufferu na <code>uint32_t *</code> je nejběžnější způsob, jak přečíst pole komunikačního rámce:</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>Je to nedefinované chování hned dvakrát. Adresa nemusí být zarovnaná na čtyři bajty (hard fault na Cortex-M0, pomalý přístup jinde) a přístup přes ukazatel jiného typu porušuje pravidla aliasingu, takže ho optimalizátor může přeuspořádat nebo zahodit. Dvě správná řešení: <code>memcpy</code> (překladač z něj udělá jediné načtení, kde to hardware dovolí) nebo složení z bajtů, které zároveň určí pořadí bajtů a nezávisí na endianitě 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>Přetypování z <code>void *</code> je typické pro generický kontext callbacku. Je advisory, protože v C je to někdy jediná cesta. Přínos pravidla je v tom, že si všimnete každého takového místa a přetypování uděláte na jediném řádku na začátku funkce (jako v <a class="" href="https://embedbits.cz/cs/blog/solid-principles-c-cpp">článku o SOLID</a>), a ne všude.</p>
<p><strong>Kdo to najde:</strong> každý analyzátor. Překladač přetypování najde jen na některých cílech a s <code>-Wcast-align</code>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-813---ukazatel-na-const-kdykoli-je-to-možné-advisory">Rule 8.13 - ukazatel na const, kdykoli je to možné (Advisory)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-813---ukazatel-na-const-kdykoli-je-to-mo%C5%BEn%C3%A9-advisory" class="hash-link" aria-label="Přímý odkaz na Rule 8.13 - ukazatel na const, kdykoli je to možné (Advisory)" title="Přímý odkaz na Rule 8.13 - ukazatel na const, kdykoli je to možné (Advisory)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> pokud funkce nemění data, na která ukazatel míří, ukazatel se deklaruje jako ukazatel na <code>const</code>.</p>
<p><strong>Co za to získáte:</strong> signatura je smlouva. Volající z prototypu vidí, že funkce data jen čte, a překladač to hlídá. <code>const</code> buffer z flash lze předat jen funkci s <code>const</code>, jinak se kód nepřeloží (nebo hůř, zapíše do flash a způsobí chybu).</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="pravidla-o-kódu-který-jste-napsali-a-kódu-který-tam-není">Pravidla o kódu, který jste napsali, a kódu, který tam není<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#pravidla-o-k%C3%B3du-kter%C3%BD-jste-napsali-a-k%C3%B3du-kter%C3%BD-tam-nen%C3%AD" class="hash-link" aria-label="Přímý odkaz na Pravidla o kódu, který jste napsali, a kódu, který tam není" title="Přímý odkaz na Pravidla o kódu, který jste napsali, a kódu, který tam není" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-177-a-directive-47---neignorujte-výsledky-required">Rule 17.7 a Directive 4.7 - neignorujte výsledky (Required)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-177-a-directive-47---neignorujte-v%C3%BDsledky-required" class="hash-link" aria-label="Přímý odkaz na Rule 17.7 a Directive 4.7 - neignorujte výsledky (Required)" title="Přímý odkaz na Rule 17.7 a Directive 4.7 - neignorujte výsledky (Required)" translate="no">​</a></h4>
<p><strong>Pravidla:</strong> vrácená hodnota se musí použít (17.7) a když funkce vrací chybový kód, musí se otestovat (4.7).</p>
<p><strong>Co za to získáte:</strong> ignorovaná návratová hodnota je ignorovaná chyba. Odeslání rámce na zaneprázdněné UART, odmítnutý zápis do flash, timeout I2C: to všechno tiše projde a aplikace pokračuje se špatným předpokladem. Pokud vás to opravdu nezajímá, řekněte to pomocí <code>(void)</code>, aby čtenář (i analyzátor) věděl, že šlo o rozhodnutí, a ne o omyl:</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>Kdo to najde:</strong> analyzátor, v gcc pomocí <code>__attribute__((warn_unused_result))</code> na vašem vlastním API.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rules-21-a-22---žádný-nedosažitelný-ani-mrtvý-kód-required">Rules 2.1 a 2.2 - žádný nedosažitelný ani mrtvý kód (Required)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rules-21-a-22---%C5%BE%C3%A1dn%C3%BD-nedosa%C5%BEiteln%C3%BD-ani-mrtv%C3%BD-k%C3%B3d-required" class="hash-link" aria-label="Přímý odkaz na Rules 2.1 a 2.2 - žádný nedosažitelný ani mrtvý kód (Required)" title="Přímý odkaz na Rules 2.1 a 2.2 - žádný nedosažitelný ani mrtvý kód (Required)" translate="no">​</a></h4>
<p><strong>Pravidla:</strong> projekt nesmí obsahovat kód, který nelze nikdy provést (2.1), a kód, který se provádí, ale nemá vliv na výsledek (2.2).</p>
<p><strong>Co za to získáte:</strong> oba druhy jsou signálem chyby: podmínka, která nikdy nenastane, zapomenutý <code>return</code> nebo chyba při copy-paste. Mrtvý kód také falšuje pokrytí testy (nedosáhnete 100 % řádků, které žádný vstup neprovede) a nutí čtenáře nad ním přemýšlet. Obojí se objevuje v této funkci:</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>První přiřazení do <code>level</code> je mrtvé a poslední řádek je nedosažitelný.</p>
<p><strong>Kdo to najde:</strong> analyzátor. gcc s <code>-Wall -Wextra</code> v mém testu mlčel.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rule-207-a-directive-49---makra-s-parametry-required--advisory">Rule 20.7 a Directive 4.9 - makra s parametry (Required / Advisory)<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#rule-207-a-directive-49---makra-s-parametry-required--advisory" class="hash-link" aria-label="Přímý odkaz na Rule 20.7 a Directive 4.9 - makra s parametry (Required / Advisory)" title="Přímý odkaz na Rule 20.7 a Directive 4.9 - makra s parametry (Required / Advisory)" translate="no">​</a></h4>
<p><strong>Pravidlo:</strong> rozvinutý parametr makra musí být v závorkách (20.7) a funkce má přednost před makrem podobným funkci (4.9).</p>
<p><strong>Co za to získáte:</strong> makro je textová náhrada. Pokud parametr nechráníte, rozhoduje priorita operátorů <em>volajícího</em>:</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>I chráněné makro má problém: <code>SQUARE_OK(count++)</code> inkrementuje dvakrát. Proto direktiva 4.9 doporučuje funkci. Inline funkce má typ, vyhodnotí argument jednou a stojí stejně:</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="misra-v-reálném-projektu">MISRA v reálném projektu<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#misra-v-re%C3%A1ln%C3%A9m-projektu" class="hash-link" aria-label="Přímý odkaz na MISRA v reálném projektu" title="Přímý odkaz na MISRA v reálném projektu" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="varování-překladače-jsou-první-krok-ne-poslední">Varování překladače jsou první krok, ne poslední<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#varov%C3%A1n%C3%AD-p%C5%99eklada%C4%8De-jsou-prvn%C3%AD-krok-ne-posledn%C3%AD" class="hash-link" aria-label="Přímý odkaz na Varování překladače jsou první krok, ne poslední" title="Přímý odkaz na Varování překladače jsou první krok, ne poslední" translate="no">​</a></h3>
<p>Všechny příklady výše jsem přeložil pomocí <code>gcc -Wall -Wextra -Wconversion -Wshadow -Wswitch-default -Wimplicit-fallthrough -O2</code>. gcc ohlásil pět varování, která patří jen ke třem „špatným“ příkladům: porovnání s povýšeným doplňkem, <code>switch</code> (chybějící <code>default</code>, neošetřená hodnota enum a propadnutí) a chybějící závorky kolem <code>==</code> v testu masky. Mlčel o zúžení, neinicializované proměnné, mrtvém a nedosažitelném kódu, přetečení se znaménkem, rekurzi, přetypování ukazatele a makru.</p>
<p>Doporučuji jako základ překladač s maximem varování a <code>-Werror</code> v CI. Je to zadarmo a odstraní to nejviditelnější problémy, ale statickou analýzu to nenahrazuje.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vyberte-nástroj-a-dejte-ho-do-ci">Vyberte nástroj a dejte ho do CI<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#vyberte-n%C3%A1stroj-a-dejte-ho-do-ci" class="hash-link" aria-label="Přímý odkaz na Vyberte nástroj a dejte ho do CI" title="Přímý odkaz na Vyberte nástroj a dejte ho do CI" translate="no">​</a></h3>
<p>Ke kontrole pravidel potřebujete statický analyzátor. Existují komerční (Polyspace, Helix QAC, PC-lint Plus, Coverity, Parasoft C/C++test, LDRA, IAR C-STAT a další) i volné, které pokrývají část pravidel, například <a href="https://cppcheck.sourceforge.io/" target="_blank" rel="noopener noreferrer" class="">cppcheck</a> s doplňkem pro MISRA. Doplněk potřebuje jako vstup text pravidel a kvůli autorským právům ho musíte dodat z vlastního výtisku normy. Nástroj nikdy není dokonalý: u nerozhodnutelných pravidel budete mít falešné poplachy a občas se porušení přehlédne.</p>
<p>Kontrola patří do CI při každém commitu, ne do ručního spuštění před vydáním. Jinak děláte stejnou práci třikrát: jednou při psaní, jednou při nalezení porušení a jednou při jeho opravě.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="výjimky-jsou-součástí-systému">Výjimky jsou součástí systému<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#v%C3%BDjimky-jsou-sou%C4%8D%C3%A1st%C3%AD-syst%C3%A9mu" class="hash-link" aria-label="Přímý odkaz na Výjimky jsou součástí systému" title="Přímý odkaz na Výjimky jsou součástí systému" translate="no">​</a></h3>
<p>Někdy je nutné pravidlo porušit. Přístup k hardwarovému registru potřebuje přetypování celého čísla na ukazatel, bootloader potřebuje zapisovat do flash přes ukazatel. MISRA to ví a definuje <strong>deviation</strong> (výjimku): záznam s pravidlem, místem, důvodem a posouzením rizika. Záznam by měl být vedle kódu:</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>Výjimka není selhání. Seznam dobře podložených výjimek je znamením projektu, ve kterém lidé přemýšlejí. Projekt s nulou výjimek a bez přístupu k hardwaru buď lže, nebo je velmi malý.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="legacy-kód-a-kód-od-dodavatelů">Legacy kód a kód od dodavatelů<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#legacy-k%C3%B3d-a-k%C3%B3d-od-dodavatel%C5%AF" class="hash-link" aria-label="Přímý odkaz na Legacy kód a kód od dodavatelů" title="Přímý odkaz na Legacy kód a kód od dodavatelů" translate="no">​</a></h3>
<p>200 000 řádků starého projektu nezpůsobíte vyhovujícími za týden. Co funguje:</p>
<ol>
<li class=""><strong>Nesahejte na starý kód,</strong> zapněte kontrolu pro <em>nové a změněné</em> soubory. Baseline analyzátoru uloží stávající porušení a CI selže jen na nových.</li>
<li class=""><strong>Začněte s pravidly mandatory a required,</strong> advisory až později.</li>
<li class=""><strong>Vyjměte kód třetích stran</strong> a zdokumentujte to. Generovaný kód dodavatele (HAL, LL, CMSIS) není vaše věc opravovat. To je další důvod pro vrstvenou architekturu z článku o <a class="" href="https://embedbits.cz/cs/blog/design-architecture">návrhu a architektuře</a>: když kód dodavatele sedí v RAL a MCAL a vše nad ním je váš kód, hranicí kontroly je složka.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-nepomáhá">Co nepomáhá<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#co-nepom%C3%A1h%C3%A1" class="hash-link" aria-label="Přímý odkaz na Co nepomáhá" title="Přímý odkaz na Co nepomáhá" translate="no">​</a></h3>
<ul>
<li class=""><strong>Hon na počet porušení.</strong> Pravidlo opravené způsobem, který uspokojí nástroj a zničí smysl (přetypování přidané jen pro umlčení varování), je horší než původní stav.</li>
<li class=""><strong>Používání MISRA jako argumentu.</strong> „MISRA to říká“ není důvod. Pokud neumíte vysvětlit, před čím vás pravidlo chrání, nebudete umět rozhodnout, kdy je čas na výjimku.</li>
<li class=""><strong>Víra, že vyhovění znamená správnost.</strong> MISRA některé chyby znemožní. Požadavky, architektura, review a testy zůstávají na vás.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shrnutí">Shrnutí<a href="https://embedbits.cz/cs/blog/misra-c-rules-in-practice#shrnut%C3%AD" class="hash-link" aria-label="Přímý odkaz na Shrnutí" title="Přímý odkaz na Shrnutí" translate="no">​</a></h2>
















































































<table><thead><tr><th>Pravidlo</th><th>Stručně</th><th>Přínos</th></tr></thead><tbody><tr><td>9.1</td><td>Inicializovat před čtením</td><td>Žádné náhodné hodnoty, stejné chování v debugu i release</td></tr><tr><td>10.x</td><td>Respektovat essential types</td><td>Žádná překvapení z integer promotion a zúžení</td></tr><tr><td>Dir 4.6</td><td>Typy pevné šířky</td><td>Stejný kód znamená totéž na každém cíli</td></tr><tr><td>1.3</td><td>Žádné nedefinované chování</td><td>Optimalizátor nemůže odstranit vaše kontroly</td></tr><tr><td>14.4</td><td>Explicitní podmínky</td><td>Záměr je čitelný</td></tr><tr><td>12.1</td><td>Závorky</td><td>Žádné chyby priority</td></tr><tr><td>15.6, 15.7, 16.3, 16.4</td><td>Složené závorky, <code>else</code>, <code>break</code>, <code>default</code></td><td>Každý případ je ošetřen</td></tr><tr><td>17.2</td><td>Žádná rekurze</td><td>Využití zásobníku lze spočítat</td></tr><tr><td>Dir 4.12, 21.3</td><td>Žádná dynamická paměť</td><td>Žádná fragmentace, úniky ani překvapení v časování</td></tr><tr><td>11.3, 11.5</td><td>Žádné triky s typy ukazatelů</td><td>Žádné chyby zarovnání a aliasingu</td></tr><tr><td>8.13</td><td>Ukazatele na <code>const</code></td><td>Signatura je smlouva</td></tr><tr><td>17.7, Dir 4.7</td><td>Používat návratové hodnoty</td><td>Chyby nemizí</td></tr><tr><td>2.1, 2.2</td><td>Žádný nedosažitelný ani mrtvý kód</td><td>Chyby jsou vidět, pokrytí má smysl</td></tr><tr><td>20.7, Dir 4.9</td><td>Bezpečná makra, preferovat funkce</td><td>Žádné skryté dvojí vyhodnocení ani chyby priority</td></tr></tbody></table>
<p>Pokud si máte zapamatovat jedinou věc: <strong>pravidlo MISRA je jizva po chybě, kterou už někdo měl.</strong> Nemusíte ta pravidla mít rádi, ale je dobré vědět, po jaké chybě je každé z nich jizvou. Pak budete vědět, kdy se jím řídit a kdy napsat výjimku a převzít odpovědnost.</p>
<p>Zde popsaná pravidla jsou jen výběr. Celá sada má více než 140 směrnic a zbytek (preprocesor, standardní knihovna, struktura deklarací) stojí za to si jednou přečíst ve vlastním výtisku normy.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>C</category>
            <category>MISRA</category>
        </item>
        <item>
            <title><![CDATA[Principy SOLID: od tříd C++ k obyčejnému C]]></title>
            <link>https://embedbits.cz/cs/blog/solid-principles-c-cpp</link>
            <guid>https://embedbits.cz/cs/blog/solid-principles-c-cpp</guid>
            <pubDate>Sat, 03 Oct 2026 21:00:00 GMT</pubDate>
            <description><![CDATA[Pět písmen, která se objevují při každém pracovním pohovoru ze softwarového inženýrství. S, O, L, I a D. Principy byly popsány pro objektově orientované jazyky, a tak se běžně usuzuje: „SOLID je pro C++ a Javu, my píšeme v C, takže máme hotovo.“ Ten závěr je špatný a pokusím se ukázat proč. U každého principu najdete původní myšlenku s příkladem v C++ a potom tutéž myšlenku v C, bez tříd, bez dědičnosti a bez jediného virtual.]]></description>
            <content:encoded><![CDATA[<p>Pět písmen, která se objevují při každém pracovním pohovoru ze softwarového inženýrství. S, O, L, I a D. Principy byly popsány pro objektově orientované jazyky, a tak se běžně usuzuje: „SOLID je pro C++ a Javu, my píšeme v C, takže máme hotovo.“ Ten závěr je špatný a pokusím se ukázat proč. U každého principu najdete původní myšlenku s příkladem v C++ a potom tutéž myšlenku v C, bez tříd, bez dědičnosti a bez jediného <code>virtual</code>.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="odkud-solid-pochází">Odkud SOLID pochází<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#odkud-solid-poch%C3%A1z%C3%AD" class="hash-link" aria-label="Přímý odkaz na Odkud SOLID pochází" title="Přímý odkaz na Odkud SOLID pochází" translate="no">​</a></h2>
<p>Principy shromáždil Robert C. Martin („Uncle Bob“) na počátku 21. století, samotnou zkratku vymyslel Michael Feathers. Některé myšlenky jsou mnohem starší: <em>open/closed principle</em> pochází od Bertranda Meyera (1988) a <em>Liskov substitution principle</em> od Barbary Liskovové (1987).</p>
<p>Všechny odpovídají na jednu otázku: <strong>jak psát kód, který přežije změnu?</strong> Ne kód, který funguje dnes, ale kód, který lze rozšiřovat, testovat a udržovat tím chlapíkem z citátu na titulní straně, který ví, kde bydlíte.</p>
<p>Příklady v C++ používají třídy a virtuální funkce, protože tak byly principy původně vysvětlovány. Příklady v C se řídí <a class="" href="https://embedbits.cz/cs/docs/platform/embi-platform/coding-style">mým coding stylem</a>: názvy <code>Module_Function</code>, typy <code>_t</code> a proměnné se smysluplnými jmény. Jedna výjimka kvůli délce: používám prosté <code>uint8_t</code>, <code>uint32_t</code> a <code>float</code> tam, kde by skutečný projekt použil vlastní typedefy (<code>temperature_t</code>, <code>voltage_t</code>), které coding style vyžaduje. Všechny příklady v tomto článku byly přeloženy (<code>gcc -std=c11 -Wall -Wextra -pedantic</code> a <code>g++ -std=c++17</code>) a spuštěny s malým unit testem, včetně těch „špatných“.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-třída-doopravdy-je">Co třída doopravdy je<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#co-t%C5%99%C3%ADda-doopravdy-je" class="hash-link" aria-label="Přímý odkaz na Co třída doopravdy je" title="Přímý odkaz na Co třída doopravdy je" translate="no">​</a></h3>
<p>Než začneme, krátká připomínka, co překladač dělá v zákulisí. Třída C++ s virtuálními funkcemi je:</p>
<ul>
<li class=""><code>struct</code> s daty objektu,</li>
<li class="">skrytý ukazatel v této struktuře na tabulku ukazatelů na funkce (<em>vtable</em>), jedna tabulka na třídu,</li>
<li class="">konvence, že každá metoda dostane ukazatel na objekt jako první parametr (<code>this</code>).</li>
</ul>
<p>V C můžeme napsat úplně totéž ručně: <code>struct</code> s daty, <code>const struct</code> s ukazateli na funkce a <code>void *context</code> jako náhradu za <code>this</code>. Pamatujte na to, celý článek na tom stojí. C++ vám zde nedává novou schopnost, jen za vás píše šablonový kód a kontroluje ho při překladu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="s---single-responsibility-principle">S - Single Responsibility Principle<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#s---single-responsibility-principle" class="hash-link" aria-label="Přímý odkaz na S - Single Responsibility Principle" title="Přímý odkaz na S - Single Responsibility Principle" translate="no">​</a></h2>
<blockquote>
<p>Modul by měl mít jeden, a jen jeden, důvod ke změně.</p>
</blockquote>
<p>„Důvod ke změně“ je ta důležitá část. Neznamená „třída má jednu metodu“. Znamená, že každá část kódu odpovídá jednomu zdroji změn: když se vymění senzor, změní se jen převod, když zákazník chce jiný formát logu, změní se jen formátování.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="v-c">V C++<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c" class="hash-link" aria-label="Přímý odkaz na V C++" title="Přímý odkaz na V C++" translate="no">​</a></h3>
<p>Následující třída dělá všechno: čte ADC, převádí hodnotu, formátuje text a odesílá ho. Čtyři důvody ke změně na jednom místě:</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>Každá změna (nový senzor, log přes CAN místo UART, jiný formát textu) upravuje tutéž třídu a nic z toho nelze otestovat bez hardwaru. Řešením je oddělit odpovědnosti a nechat monitor, aby je jen propojil:</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="v-c-1">V C<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-1" class="hash-link" aria-label="Přímý odkaz na V C" title="Přímý odkaz na V C" translate="no">​</a></h3>
<p>Přesně stejná chyba je možná, a běžná, i v obyčejném C, kde obvykle vypadá jako jedna dlouhá funkce v <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>Nástrojem pro oddělení v C je <strong>modul</strong>: dvojice souborů <code>.h</code>/<code>.c</code> se společným prefixem, kde hlavička je veřejné rozhraní a všechno ostatní je <code>static</code>. Jeden modul, jedna odpovědnost:</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>Modul ADC (<code>Adc.h</code>) je stejná myšlenka a monitor jen propojuje moduly:</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>Pokud se TMP36 nahradí NTC, vymění se jen <code>Tmp36.c</code>. Pokud log půjde přes CAN místo UART, změní se jen <code>Logger.c</code>. A <code>Tmp36_Get_Celsius()</code> lze testovat na vašem PC obyčejným <code>assert</code>, protože se nedotýká žádného registru.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="o---openclosed-principle">O - Open/Closed Principle<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#o---openclosed-principle" class="hash-link" aria-label="Přímý odkaz na O - Open/Closed Principle" title="Přímý odkaz na O - Open/Closed Principle" translate="no">​</a></h2>
<blockquote>
<p>Softwarové entity by měly být otevřené pro rozšíření, ale uzavřené pro modifikaci.</p>
</blockquote>
<p>Měli byste být schopni přidat nové chování bez úprav kódu, který už funguje a je otestovaný. Typický zápach je <code>switch</code> nad typem, který roste s každou novou funkcí.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="v-c-2">V C++<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-2" class="hash-link" aria-label="Přímý odkaz na V C++" title="Přímý odkaz na V C++" translate="no">​</a></h3>
<p>Níže uvedená pipeline se musí upravit pro každý nový filtr, včetně <code>enum</code> a <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>Řešením je abstrakce (rozhraní), kterou pipeline zná a nové filtry ji implementují:</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>Nový filtr je nová třída. <code>SamplePipeline</code> je uzavřená pro modifikaci a systém je otevřený pro rozšíření.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="v-c-3">V C<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-3" class="hash-link" aria-label="Přímý odkaz na V C" title="Přímý odkaz na V C" translate="no">​</a></h3>
<p>Stejný problém se <code>switch</code> v 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>Náhradou virtuální tabulky v C je <strong>tabulka ukazatelů na funkce</strong> a <code>void *context</code> pro data instance. Abstrakce se definuje jednou:</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>Každý filtr je dvojice dat (<code>context</code>) a konstantní tabulky s chováním:</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>Druhý filtr je zcela samostatný modul, první se nedotkl:</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>Pipeline zná jen <code>filter_t</code>, takže se už nikdy nemusí měnit:</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>A takto se používá. Oba filtry pracují se stejnou 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>Tabulky jsou <code>const</code>, takže žijí ve flash a nestojí žádnou RAM. To, co překladač C++ generuje pro <code>virtual</code>, je přesně tohle.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="l---liskov-substitution-principle">L - Liskov Substitution Principle<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#l---liskov-substitution-principle" class="hash-link" aria-label="Přímý odkaz na L - Liskov Substitution Principle" title="Přímý odkaz na L - Liskov Substitution Principle" translate="no">​</a></h2>
<blockquote>
<p>Objekty podtypu musí být použitelné všude, kde se očekává základní typ, aniž by volající poznal rozdíl.</p>
</blockquote>
<p>Toto je nejméně chápaný princip. Netýká se syntaxe (tu za vás kontroluje překladač), týká se <strong>kontraktu</strong>. Odvozená třída nesmí vyžadovat víc, než základní třída slibuje, a nesmí dodat méně. Pokud volající potřebuje <code>if (typeid(...))</code>, princip je porušen.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="v-c-4">V C++<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-4" class="hash-link" aria-label="Přímý odkaz na V C++" title="Přímý odkaz na V C++" translate="no">​</a></h3>
<p>Tři paměťová zařízení za jedním rozhraním. Které z nich porušuje kontrakt?</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> vyžaduje zarovnané adresy a délky, o čemž základní třída nikdy nemluvila, takže kód, který ukládá pět bajtů, funguje s <code>Eeprom</code> a tiše selže s <code>Flash</code>. <code>RomImage</code> vyhazuje výjimku v systému, který se pravděpodobně staví s <code>-fno-exceptions</code>. Všechny tři se přeloží a chová se správně jen jedno.</p>
<p>Oprava spočívá v dodržení kontraktu v implementaci a v nedědění tam, kde schopnost chybí:</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="v-c-5">V C<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-5" class="hash-link" aria-label="Přímý odkaz na V C" title="Přímý odkaz na V C" translate="no">​</a></h3>
<p>C nemá dědičnost, takže je princip nepodstatný? Naopak, tabulka ukazatelů na funkce je rozhraní přesně jako v C++ a problém substituce je stejný. V C je to ještě nebezpečnější, protože typickými porušeními jsou <code>NULL</code> v tabulce nebo <code>assert</code> v implementaci:</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>Lék je stejný jako v C++, plus jeden zvyk: <strong>napište kontrakt do hlavičky</strong> a přinuťte všechny implementace, aby ho dodržovaly. Žádné <code>NULL</code> v tabulce, žádný assert pro chybu volajícího, žádná skrytá předpodmínka:</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> funguje s flash, s obrazem ROM (dostane normální chybový kód) i s jakoukoli implementací, která přibude později.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="i---interface-segregation-principle">I - Interface Segregation Principle<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#i---interface-segregation-principle" class="hash-link" aria-label="Přímý odkaz na I - Interface Segregation Principle" title="Přímý odkaz na I - Interface Segregation Principle" translate="no">​</a></h2>
<blockquote>
<p>Klienti by neměli být nuceni záviset na metodách, které nepoužívají.</p>
</blockquote>
<p>„Tlusté“ rozhraní svazuje každého se vším. Když UART dostane novou metodu, musí se přeložit znovu a zrevidovat každý klient a každý mock, i když chtěl jen odesílat bajty.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="v-c-6">V C++<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-6" class="hash-link" aria-label="Přímý odkaz na V C++" title="Přímý odkaz na V C++" translate="no">​</a></h3>
<p>Logger potřebuje jednu metodu, ale závisí na pěti:</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>Rozhraní se rozdělí podle role klienta. Konfigurace zůstane na konkrétní třídě a logger žádá jen o schopnost zapisovat bajty:</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>Mock pro test loggeru má nyní jednu metodu místo pěti.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="v-c-7">V C<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-7" class="hash-link" aria-label="Přímý odkaz na V C" title="Přímý odkaz na V C" translate="no">​</a></h3>
<p>Tlusté rozhraní existuje i v C jako obrovská struktura ukazatelů na funkce nebo, častěji, jako jeden obří hlavičkový soubor <code>Uart.h</code>, který vkládá každý:</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>Existují dva nástroje. První je stejný jako v C++: malé rozhraní (<code>byteSink_t</code>), které nese jen to, co klient potřebuje:</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>Druhý je specifický pro C: <strong>rozdělte hlavičku</strong>. Každý, kdo jen odesílá bajty, vkládá <code>Uart_Tx.h</code> a nikdo jiný konfiguraci nevidí:</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>Logger lze otestovat třířádkovou funkcí, která zachytává bajty. Neví, že UART existuje.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="d---dependency-inversion-principle">D - Dependency Inversion Principle<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#d---dependency-inversion-principle" class="hash-link" aria-label="Přímý odkaz na D - Dependency Inversion Principle" title="Přímý odkaz na D - Dependency Inversion Principle" translate="no">​</a></h2>
<blockquote>
<p>Moduly na vysoké úrovni by neměly záviset na modulech na nízké úrovni. Obě strany by měly záviset na abstrakcích. Abstrakce by neměly záviset na detailech.</p>
</blockquote>
<p>Tento princip spojuje ostatní čtyři. Stojí za vrstvami z článku o <a class="" href="https://embedbits.cz/cs/blog/design-architecture">designu a architektuře</a>: aplikace nesmí vědět, který registr přepíná LED.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="v-c-8">V C++<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#v-c-8" class="hash-link" aria-label="Přímý odkaz na V C++" title="Přímý odkaz na V C++" translate="no">​</a></h3>
<p>Termostat (politika na vysoké úrovni) obsahuje třídy ADC a GPIO (detaily na nízké úrovni). Nelze ho přeložit bez hardwaru, nelze ho testovat na PC a nelze ho přenést na jinou desku:</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>Po inverzi vlastní rozhraní politika a ovladače je implementují. Šipka závislosti míří k politice:</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">In C<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#in-c" class="hash-link" aria-label="Přímý odkaz na In C" title="Přímý odkaz na In C" translate="no">​</a></h3>
<p>C nabízí dvě cesty a ta druhá je pro C jedinečná a levnější než jakékoli virtuální volání.</p>
<p><strong>1. Injekce za běhu</strong> pomocí ukazatelů na funkce, přesně jako v příkladu open/closed. Rozhraní patří termostatu (je v <code>Thermostat.h</code>) a ovladače ho naplňují:</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>V unit testu předáte funkce, které vracejí číslo a pamatují si stav topení. Na cílové platformě předáte <code>Adc_Get_Celsius</code> a <code>Gpio_Set_Heater</code> a <code>Thermostat.c</code> zůstane nedotčen.</p>
<p><strong>2. Injekce při linkování.</strong> Někdy nepotřebujete přepínat implementace za běhu, stačí se rozhodnout jednou, v build systému. Pak je abstrakcí <strong>hlavička s deklaracemi</strong> a implementací zdrojový soubor, který CMake vybere pro daný 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>Pro desku se linkuje <code>Bsp_Thermostat_Stm32.c</code>, který implementuje obě funkce se skutečnými periferiemi. V unit testu na PC se místo něj linkuje <code>Bsp_Thermostat_Fake.c</code>. Žádné ukazatele na funkce, žádná nepřímost, žádná RAM a termostat je stále zcela nezávislý na hardwaru. To je mimochodem přesně to, co dělá BSP Embedbits: aplikace volá rozhraní BSP a nezajímá ji, jaká rodina nebo deska je za ním.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="stejné-myšlenky-ve-dvou-jazycích">Stejné myšlenky ve dvou jazycích<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#stejn%C3%A9-my%C5%A1lenky-ve-dvou-jazyc%C3%ADch" class="hash-link" aria-label="Přímý odkaz na Stejné myšlenky ve dvou jazycích" title="Přímý odkaz na Stejné myšlenky ve dvou jazycích" translate="no">​</a></h2>



































<table><thead><tr><th>Princip</th><th>C++</th><th>C</th></tr></thead><tbody><tr><td><strong>S</strong></td><td>třída</td><td>modul (dvojice <code>.h</code>/<code>.c</code>, prefix, <code>static</code>)</td></tr><tr><td><strong>O</strong></td><td>abstraktní třída, <code>virtual</code>, <code>override</code></td><td><code>const</code> tabulka ukazatelů na funkce + <code>void *context</code></td></tr><tr><td><strong>L</strong></td><td>kontrakt základní třídy</td><td>kontrakt zapsaný v hlavičce, žádné <code>NULL</code> v tabulce</td></tr><tr><td><strong>I</strong></td><td>několik malých rozhraní</td><td>malé struktury ukazatelů, rozdělené hlavičky</td></tr><tr><td><strong>D</strong></td><td>injekce rozhraní konstruktorem</td><td>ukazatele na funkce ve <code>struct</code> nebo injekce při linkování</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="co-za-vás-překladač-neudělá">Co za vás překladač neudělá<a href="https://embedbits.cz/cs/blog/solid-principles-c-cpp#co-za-v%C3%A1s-p%C5%99eklada%C4%8D-neud%C4%9Bl%C3%A1" class="hash-link" aria-label="Přímý odkaz na Co za vás překladač neudělá" title="Přímý odkaz na Co za vás překladač neudělá" translate="no">​</a></h2>
<p>Je namístě poctivost. C++ má výhody, které musíte v C nahradit disciplínou:</p>
<ul>
<li class=""><strong>Žádná kontrola při překladu.</strong> Pokud se zapomene pole tabulky funkcí, překladač mlčí (designated initializers alespoň pojmenují pole a v C se chybějící stane <code>NULL</code>). Používejte inicializátory <code>.Process = ...</code>, nikdy poziční, a mějte unit test, který volá každou funkci každé implementace.</li>
<li class=""><strong><code>void *context</code> není typově bezpečný.</strong> Špatné přetypování překladač nenajde. Držte přetypování na jednom řádku na začátku každé funkce (<code>movingAverage_t *self = context;</code>) a nikde jinde.</li>
<li class=""><strong>Náklady.</strong> Nepřímé volání stojí několik cyklů a tabulky stojí flash. Na Cortex-M to obvykle nevadí, ale ne v přerušení, které běží každých 10 mikrosekund. Tam je varianta při linkování zdarma.</li>
</ul>
<p>A největší past: <strong>SOLID je soubor doporučení, ne zákon</strong>. Rozdělit 30řádkovou funkci na pět modulů s tabulkami ukazatelů na funkce, protože „to říká princip“, je vlastní druh špaget. Použijte princip, když existuje skutečný důvod ke změně, druhá implementace nebo unit test, který bez něj nelze napsat. Ne dřív.</p>
<p>Pokud si z tohoto článku zapamatujete jednu větu, ať je to tato: <strong>principy se týkají směru závislostí a velikosti částí, ne tříd.</strong> C++ vám dává třídy, C vám dává moduly a ukazatele na funkce. Dobrý návrh nepotřebuje ani jedno z toho, aby byl efektní.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>Architektura</category>
            <category>C</category>
            <category>C++</category>
        </item>
        <item>
            <title><![CDATA[Návrh a architektura]]></title>
            <link>https://embedbits.cz/cs/blog/design-architecture</link>
            <guid>https://embedbits.cz/cs/blog/design-architecture</guid>
            <pubDate>Sun, 29 Sep 2024 20:59:52 GMT</pubDate>
            <description><![CDATA[OCD. Tři skvělá písmena, která mě nutí neustále přemýšlet o architektuře softwaru. To může být opravdu bolestivé, zvlášť když se musím potýkat s architekturou v „arduinovském" stylu. Určitě ji znáte: celý projekt v pár složkách, aplikace ve složce src, nízkoúrovňová funkcionalita ve složce driver a tak dále. Ale co dělat ve složitých systémech?]]></description>
            <content:encoded><![CDATA[<p>OCD. Tři skvělá písmena, která mě nutí neustále přemýšlet o architektuře softwaru. To může být opravdu bolestivé, zvlášť když se musím potýkat s architekturou v „arduinovském" stylu. Určitě ji znáte: celý projekt v pár složkách, aplikace ve složce <em>src</em>, nízkoúrovňová funkcionalita ve složce <em>driver</em> a tak dále. Ale co dělat ve složitých systémech?</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="modularita">Modularita<a href="https://embedbits.cz/cs/blog/design-architecture#modularita" class="hash-link" aria-label="Přímý odkaz na Modularita" title="Přímý odkaz na Modularita" translate="no">​</a></h2>
<p>Každá skupina funkcionality má být zapouzdřena v balíčku. Propojováním takových balíčků dostáváme stále složitější systémy. Představte si projekt, kde chcete měřit teplotu senzorem připojeným k ADC a aktuální data posílat přes UART. Potřebujeme modul, který čte surová data z ADC, vypočítá hodnotu ve °C a poskytne ji na svém rozhraní, a další modul, který obsluhuje komunikaci přes UART.</p>
<p>Kdybychom všechnu tuto funkcionalitu spojili na jednom místě, určovali bychom polohu a rychlost elementární částice současně. To by způsobilo kolaps vlnové funkce a zničení vesmíru (sarkasmus).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="abstrakční-vrstvy">Abstrakční vrstvy<a href="https://embedbits.cz/cs/blog/design-architecture#abstrak%C4%8Dn%C3%AD-vrstvy" class="hash-link" aria-label="Přímý odkaz na Abstrakční vrstvy" title="Přímý odkaz na Abstrakční vrstvy" translate="no">​</a></h2>
<p>Představte si strom. Vrchol stromu je jediný bod, který řeší nebo vykonává požadovanou funkcionalitu. V embedded systémech to může být nekonečná smyčka ve funkci main nebo nějaký RTOS handler. Čím níže strom jde, tím je širší. To představuje propojení a hierarchii mezi moduly. Kořeny stromu představují spojení s hardwarem.</p>
<p>Základním příkladem je „blinky": LED připojená k PA1 má být aktivní, pokud je stisknuto tlačítko připojené k PA0, a naopak.</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>V tomto příkladu jsme smíchali všechny vrstvy. Pro primitivní projekt to může být přijatelné, ale ve složitém systému to vede k anarchii, nepořádku, špagetovému kódu <strong>a konci světa</strong>. Aby se předešlo ubohému, dlouhému a zásadnímu armagedonu, lidé vymysleli pár skvělých věcí, jako jsou hierarchie a abstrakční vrstvy. Ve svých projektech rozděluji funkcionalitu do tří základních vrstev: Application, Middleware a Board Support Package (alias BSP). Ty se dále dělí na více vrstev, aby se dosáhlo přenositelnosti a modularity.</p>
<p><img decoding="async" loading="lazy" alt="Struktura složek projektu: Application, Artifacts, Bsp (Hal, LinkerFiles, Mcal, Ral, Startup), Docs a 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><em>Application</em> obsahuje to, co produkt dělá. <em>Middleware</em> obsahuje znovupoužitelný software bez závislosti na hardwaru, jako je logger, zásobník ModBus nebo správce nevolatilní paměti. A co je to BSP? Jednoduché. Obsahuje vše potřebné pro komunikaci, konfiguraci a obsluhu hardwaru. Z našeho příkladu výše patří operace s GPIO do BSP. Uživatele nemá zajímat přesné zapojení tlačítka a LED, takže rozhraní mezi BSP a aplikací může vypadat jako <em><strong>Bsp_Get_ButtonState()</strong></em> a <em><strong>Bsp_Set_LedState()</strong></em>. Pokud se v hardwaru cokoli změní, nikdo nemusí upravovat více míst a aktualizuje se jen BSP.</p>
<p>BSP tedy obsahuje alespoň jednu vrstvu zapouzdření pro tyto gettery a settery. Ale co budou používat? Budou zapisovat přímo do registrů? Nemyslím si. STMicroelectronics má dvě sady „ovladačů": „HAL" a „LL". Proč ty uvozovky? Protože ani jeden název není správný. Jejich balíček „HAL" je ve skutečnosti obrovský a pomalý špagetový kód, který nemá nic společného se svým popisem, protože HAL znamená Hardware Abstraction Layer. K té skutečné se dostaneme na konci.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="register-abstraction-layer-ral">Register Abstraction Layer (RAL)<a href="https://embedbits.cz/cs/blog/design-architecture#register-abstraction-layer-ral" class="hash-link" aria-label="Přímý odkaz na Register Abstraction Layer (RAL)" title="Přímý odkaz na Register Abstraction Layer (RAL)" translate="no">​</a></h2>
<p>Funkce <code>LL_GPIO_xxx</code> z příkladu jsou zapouzdřený přístup k registrům MCU. Operace s registry můžete psát kdekoli, ale co když změníte MCU nebo uděláte chybu? Musíte to opravit na každém jednotlivém místě. To by bylo bolestivé, takže jsme právě našli nejnižší abstrakční vrstvu, <em>Register Abstraction Layer</em>. Představuje pouze abstrakci registrů, zapouzdřenou ve (obvykle inline) funkcích se smysluplnými názvy.</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>Název „LL" je z mého pohledu nesprávný (stejně jako jejich HAL, ale kdo by ho používal?), ale získáme přístup ke všem registrům se smysluplným popisem, takže ho můžeme používat bez náročného ručního psaní.</p>
<p>V mých projektech se RAL skládá ze tří částí:</p>
<ul>
<li class=""><strong>CMSIS</strong> od ARM: definice jádra Cortex-M,</li>
<li class=""><strong>CMSIS_ST</strong> od STMicroelectronics: hlavičky zařízení s definicemi registrů a systémovou inicializací rodiny MCU,</li>
<li class=""><strong>RAL_ST</strong>: původní ovladače LL od ST spolu s mou vrstvou <code>Port</code>. Vrstva <code>Port</code> poskytuje jednotné pojmenování nezávislé na rodině MCU, takže se kód nad RAL nemění, když se změní MCU.</li>
</ul>
<p>RAL zná registry a nic jiného. Neví, že něco je připojeno k PA1.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="microcontroller-abstraction-layer-mcal">Microcontroller Abstraction Layer (MCAL)<a href="https://embedbits.cz/cs/blog/design-architecture#microcontroller-abstraction-layer-mcal" class="hash-link" aria-label="Přímý odkaz na Microcontroller Abstraction Layer (MCAL)" title="Přímý odkaz na Microcontroller Abstraction Layer (MCAL)" translate="no">​</a></h2>
<p>Máme tedy snadný přístup k registrům. Co ale dál? Přístup k GPIO je triviální, ale co ostatní periferie? Pro přenos přes UART potřebujeme pro každou operaci více registrů: aktivovat periferii, nastavit baudrate, délku bitu, paritu, stop bity a tak dále. A protože už víme, že každá funkcionalita používaná více než jednou má být zapouzdřena, vytvoříme funkce pro čtení chyb, zahájení přenosu, zápis do výstupního datového registru, čtení ze vstupního datového registru a mnoho dalších.</p>
<p>Tato funkcionalita nemůže být RAL, protože je hierarchicky výše a RAL volá. Stará se pouze o periferie mikrokontroléru, takže název této vrstvy je <em>Microcontroller Abstraction Layer</em> (MCAL). Uživatel vidí <code>Gpio_Set_PinLevel()</code> nebo <code>Usart_Send()</code> a nepotřebuje znát jediný registr. Jedna periferie, jedno rozhraní: pokud I2C potřebuje DMA, modul I2C si ho obslouží interně.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hardware-abstraction-layer-hal">Hardware Abstraction Layer (HAL)<a href="https://embedbits.cz/cs/blog/design-architecture#hardware-abstraction-layer-hal" class="hash-link" aria-label="Přímý odkaz na Hardware Abstraction Layer (HAL)" title="Přímý odkaz na Hardware Abstraction Layer (HAL)" translate="no">​</a></h2>
<p>Nyní můžeme inicializovat všechny periferie MCU: RCC, DMA, USART/UART a tak dále. Ale konfigurace musí být kompatibilní se zařízeními připojenými na našem PCB. Nezaměřujeme se tedy jen na MCU, ale na celý obvod. Potřebujeme proto další abstrakční vrstvu, <em>Hardware Abstraction Layer</em> (HAL). Ano, toto je skutečný význam tohoto názvu, ne jako u „HAL" od ST.</p>
<p>HAL je jediný bod rozhraní mezi aplikací (nebo middlewarem) a hardwarem. Ví, který pin je LED, který UART je připojen ke konektoru pro ladění a jak jsou periferie nakonfigurovány. Pro dosažení požadované funkcionality propojuje více modulů z MCAL. Toto je poslední abstrakční vrstva BSP.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="board-support-package">Board Support Package<a href="https://embedbits.cz/cs/blog/design-architecture#board-support-package" class="hash-link" aria-label="Přímý odkaz na Board Support Package" title="Přímý odkaz na Board Support Package" translate="no">​</a></h2>
<p>BSP je balíček orientovaný na hardware, který obsahuje vše potřebné pro inicializaci a používání všech periferií MCU a připojeného obvodu. Kromě tří výše uvedených vrstev obsahuje také <strong>startup</strong> kód (inicializace paměťových sekcí a volání aplikace) a generování <strong>linker</strong> scriptu pro vybrané MCU. Každá rodina STM32 má vlastní větev, takže rozhraní BSP zůstává stejné a mění se jen obsah pod ním.</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>Pravidlo je jednoduché: <strong>vrstva volá pouze vrstvu bezprostředně pod sebou.</strong> Aplikace nikdy neincluduje hlavičku ST, MCAL neví, který pin je LED, a RAL neví, k čemu se která periferie používá.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="znovu-blinky">Znovu blinky<a href="https://embedbits.cz/cs/blog/design-architecture#znovu-blinky" class="hash-link" aria-label="Přímý odkaz na Znovu blinky" title="Přímý odkaz na Znovu blinky" translate="no">​</a></h2>
<p>Přepišme příklad. Aplikace nezná žádný 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>BSP zná desku a používá MCAL. Piny jsou popsány v jediné tabulce, takže nová revize PCB změní jeden řádek a nic jiného (zjednodušeno, ošetření chyb je vynecháno):</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>A někde úplně dole, uvnitř <code>Gpio_Set_PinLevel()</code>, funkce RAL <code>LL_GPIO_SetOutputPin()</code> konečně zapíše registr <code>BSRR</code>. Čtyři vrstvy pro blikající LED vypadají jako nesmysl, a pro blinky to nesmysl je. Ale jde o to, co se stane, když produkt poroste:</p>
<ul>
<li class=""><strong>Nová rodina MCU:</strong> vyzvedne se jiná větev BSP, aplikace se nedotkne.</li>
<li class=""><strong>Nová revize PCB:</strong> LED se přesune na jiný pin, změní se jeden řádek v HAL.</li>
<li class=""><strong>Unit test aplikace:</strong> BSP se nahradí falešným a aplikace běží na PC, bez jakéhokoli hardwaru.</li>
<li class=""><strong>Chyba v přístupu k registru:</strong> je přesně na jednom místě.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kde-to-najít">Kde to najít<a href="https://embedbits.cz/cs/blog/design-architecture#kde-to-naj%C3%ADt" class="hash-link" aria-label="Přímý odkaz na Kde to najít" title="Přímý odkaz na Kde to najít" translate="no">​</a></h2>
<p>Všechny zde popsané vrstvy jsou open source a zdokumentované, každá ve vlastním repozitáři organizace <a href="https://github.com/Embedbits" target="_blank" rel="noopener noreferrer" class="">Embedbits</a>:</p>
<ul>
<li class=""><a class="" href="https://embedbits.cz/cs/docs/bsp">BSP</a>: balíček se startupem, linker scriptem a HAL,</li>
<li class=""><a class="" href="https://embedbits.cz/cs/docs/bsp/ral">RAL</a>: CMSIS, CMSIS_ST a RAL_ST,</li>
<li class=""><a class="" href="https://embedbits.cz/cs/docs/bsp/mcal">MCAL</a>: periferní moduly spolu s tabulkou podporovaných rodin STM32,</li>
<li class=""><a class="" href="https://embedbits.cz/cs/docs/platform/embi-platform/coding-style">coding style</a>, díky kterému jsou názvy v těchto vrstvách čitelné.</li>
</ul>
<p>Pokud chcete vidět stejnou myšlenku z pohledu jazyka, přečtěte si článek o <a class="" href="https://embedbits.cz/cs/blog/solid-principles-c-cpp">principech SOLID v C++ a C</a>. Výše popsané vrstvy nejsou nic jiného než <em>dependency inversion</em> aplikovaná na celý firmware.</p>]]></content:encoded>
            <category>Embedded</category>
            <category>Architektura</category>
        </item>
        <item>
            <title><![CDATA[Konečné automaty]]></title>
            <link>https://embedbits.cz/cs/blog/finite-state-machines</link>
            <guid>https://embedbits.cz/cs/blog/finite-state-machines</guid>
            <pubDate>Sun, 29 Sep 2024 16:24:40 GMT</pubDate>
            <description><![CDATA[Pro vývoj embedded softwaru je správný návrh nezbytný. Mikrokontrolér musí zvládat zpracování samotné aplikace i komunikaci s množstvím připojených obvodů přes interní či externí periferie. Provádění aplikace má být co nejrychlejší. To je ale pro kohokoli dost hrozné vysvětlení. V reálném světě musí vývojář zajistit optimálně krátkou logickou cestu provádění kódu. To znamená, že vývojář nemá v každém hlavním cyklu kontrolovat všechny podmínky. Jedním ze způsobů této optimalizace je správné vnořování podmínek. S rostoucí složitostí projektu to může být opravdu obtížné. Množství vnořených podmíněných příkazů může vést k nestabilitě kódu a zhoršit jeho čitelnost. Čitelnost kódu je přitom kruté nutná pro budoucí úpravy nebo údržbu existujícího kódu. Jeden z mých oblíbených citátů říká:]]></description>
            <content:encoded><![CDATA[<p>Pro vývoj embedded softwaru je správný návrh nezbytný. Mikrokontrolér musí zvládat zpracování samotné aplikace i komunikaci s množstvím připojených obvodů přes interní či externí periferie. Provádění aplikace má být co nejrychlejší. To je ale pro kohokoli dost hrozné vysvětlení. V reálném světě musí vývojář zajistit optimálně krátkou logickou cestu provádění kódu. To znamená, že vývojář nemá v každém hlavním cyklu kontrolovat všechny podmínky. Jedním ze způsobů této optimalizace je správné vnořování podmínek. S rostoucí složitostí projektu to může být opravdu obtížné. Množství vnořených podmíněných příkazů může vést k nestabilitě kódu a zhoršit jeho čitelnost. Čitelnost kódu je přitom kruté nutná pro budoucí úpravy nebo údržbu existujícího kódu. Jeden z mých oblíbených citátů říká:</p>
<!-- -->
<p><img decoding="async" loading="lazy" alt="Výřez tabulky rutin konečného automatu v jazyce C" src="https://embedbits.cz/cs/assets/images/fsm-state-machine-cc3162be67be4421b1cac2bb42f51afd.png" width="551" height="586" class="img_ev3q"></p>
<blockquote>
<p><strong>Vždy programujte tak, jako by ten, kdo bude váš kód udržovat, byl násilnický psychopat, který ví, kde bydlíte.</strong></p>
</blockquote>
<p>Měli bychom tedy raději přemýšlet, než napíšeme skutečný kód. Tomuto procesu se říká „návrh“ a já ho mám opravdu rád. Protože když ho uděláte správně, množství nového kódu a následných úprav tohoto nového kódu se výrazně sníží. Někdy si můžete myslet, že to zabere příliš času, ale ve skutečnosti je tento čas sečtený s časem psaní kódu kratší než psaní kódu, který se bude neustále přepisovat. Jak to ale usnadnit? Tady můžeme začít mluvit o konečných automatech (Finite State Machines), známých také jako FSM.</p>
<p>Začněme tedy popisem generovaným umělou inteligencí, který nic neříká:</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>Co to ale znamená? Jednoduše řečeno, Mealyho konečný automat kontroluje podmínky pro požadovaný stav <em><strong>před</strong></em> provedením aktuálního stavu. Mooreův automat kontroluje podmínky <em><strong>po</strong></em> provedení aktuálního stavu.</p>
<p>Co ale stav představuje? Představte si žárovku, kterou lze zapnout a vypnout stisknutím tlačítka. Pro obsluhu tohoto chování by náš automat potřeboval jen dva stavy. Jeden stav, který aktivuje akční člen, a druhý, který tento akční člen deaktivuje. Opravdu jednoduché, že? Ale co u složitých systémů? Inu, potřebujete jednoduchou implementaci použitelnou pro různé situace. To je přesně to, co dělá šablona níže.</p>
<p>Při práci v automobilovém průmyslu jsme se s kolegou <a href="https://www.linkedin.com/in/jano-sima/" target="_blank" rel="noopener noreferrer" class="">Janem Šimou</a> setkali s problémy při návrhu konečných automatů. Existovalo množství různých stylů, ale žádný z nich neměl dostatečnou funkčnost k dosažení stability a čistého návrhu. Rozhodli jsme se proto navrhnout vlastní šablonu. S Janovým svolením zveřejňuji šablonu našeho konečného automatu pod licencí MIT.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="stažení-šablony">Stažení šablony<a href="https://embedbits.cz/cs/blog/finite-state-machines#sta%C5%BEen%C3%AD-%C5%A1ablony" class="hash-link" aria-label="Přímý odkaz na Stažení šablony" title="Přímý odkaz na Stažení šablony" translate="no">​</a></h2>
<p>Šablona je zveřejněna pod licencí MIT. Vše je čistý text, takže si ji můžete přečíst ještě před stažením:</p>

























<table><thead><tr><th>Soubor</th><th>Co to je</th></tr></thead><tbody><tr><td><a href="https://embedbits.cz/cs/downloads/fsm/FsmTemplate.c" target="_blank" rel="noopener noreferrer" class="">FsmTemplate.c</a></td><td>Šablona v jazyce <strong>C</strong> (C99), jeden soubor se stavy, tabulkou rutin a zástupnými funkcemi</td></tr><tr><td><a href="https://embedbits.cz/cs/downloads/fsm/FsmTemplate.hpp" target="_blank" rel="noopener noreferrer" class="">FsmTemplate.hpp</a> a <a href="https://embedbits.cz/cs/downloads/fsm/FsmTemplate.cpp" target="_blank" rel="noopener noreferrer" class="">FsmTemplate.cpp</a></td><td>Šablona v jazyce <strong>C++</strong> (C++17), třída s jedním automatem uvnitř</td></tr><tr><td><a href="https://embedbits.cz/cs/downloads/fsm/Fsm.hpp" target="_blank" rel="noopener noreferrer" class="">Fsm.hpp</a></td><td>Header-only jádro pro verzi v C++ (bez haldy, bez výjimek, bez RTTI)</td></tr><tr><td><a href="https://embedbits.cz/cs/downloads/fsm/fsm-instantiate.sh" target="_blank" rel="noopener noreferrer" class="">fsm-instantiate.sh</a></td><td>Malý skript, který nahradí názvy, <code>fsm-instantiate.sh Button FsmTemplate.c src/</code> vytvoří <code>src/Button.c</code></td></tr></tbody></table>
<p>Názvy ve špičatých závorkách se nahradí názvem vašeho modulu: <code>&lt;Module&gt;</code> se změní na <code>Button</code>, <code>&lt;module&gt;</code> na <code>button</code> a <code>&lt;MODULE&gt;</code> na <code>BUTTON</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="jak-to-funguje">Jak to funguje<a href="https://embedbits.cz/cs/blog/finite-state-machines#jak-to-funguje" class="hash-link" aria-label="Přímý odkaz na Jak to funguje" title="Přímý odkaz na Jak to funguje" translate="no">​</a></h2>
<p>Jde o Mooreův automat. Každý stav má čtyři rutiny a automat je při každém běhu volá ve stejném pořadí:</p>
<ol>
<li class=""><strong>Entry</strong>: volá se jednou, při vstupu do stavu.</li>
<li class=""><strong>Execute</strong>: volá se při každém běhu, zde je práce stavu.</li>
<li class=""><strong>CheckLeave</strong>: volá se při každém běhu po Execute. Je to <strong>jediné</strong> místo, kde se žádá o nový stav.</li>
<li class=""><strong>Leave</strong>: volá se jednou, při opuštění stavu.</li>
</ol>
<p>Celé jádro je jedna funkce. Toto je verze v 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">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>Protože se o přechod žádá jen v <code>CheckLeave</code>, provádějí se entry a leave stavu vždy jako dvojice, ve známém pořadí, a výstupy závisejí jen na stavu. Rutina, která není potřeba, může být <code>NULL</code> (<code>nullptr</code> v C++) a přeskočí se.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-was-fixed">Co bylo opraveno<a href="https://embedbits.cz/cs/blog/finite-state-machines#what-was-fixed" class="hash-link" aria-label="Přímý odkaz na Co bylo opraveno" title="Přímý odkaz na Co bylo opraveno" translate="no">​</a></h2>
<p>První verze šablony, kterou jsem tu zveřejnil, měla několik chyb. Znovu jsem ji prošel, přeložil a spustil proti testu, který zaznamenává pořadí volání. Toto jsou změny:</p>
<ul>
<li class="">Počáteční hodnota stavových proměnných byla zbytkový název z jiného projektu (<code>APPCORE_HANDLER_STATE_1</code> místo <code>&lt;MODULE&gt;_STATE_1</code>).</li>
<li class="">Poslední řádek tabulky používal <code>State_2_Leave</code> místo <code>State_3_Leave</code>. Kód se přeložil a při opuštění třetího stavu volal špatnou rutinu. Tabulka je nyní indexovaná stavem (<code>[&lt;MODULE&gt;_STATE_3] = { ... }</code>), takže pozici řádku nelze splést.</li>
<li class=""><code>Init</code> nespouštěla entry rutinu prvního stavu.</li>
<li class="">Čísla stavů se nekontrolovala. Poškozený aktuální stav nebo žádost o neexistující stav indexovaly mimo tabulku. Obojí se nyní kontroluje a automat se vrací do prvního stavu, který je bezpečný. Žádost se kontroluje <strong>po</strong> <code>CheckLeave</code>, protože tam vzniká. Moje první oprava to kontrolovala před, a test to odhalil, což je pěkný důkaz, proč takový test stojí za to.</li>
<li class="">Rutina s ukazatelem <code>NULL</code> se přeskočí místo pádu.</li>
<li class="">Chybějící forward deklarace a komentář v hlavičce, který po nahrazení názvů ztratil smysl.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="verze-v-c">Verze v C++<a href="https://embedbits.cz/cs/blog/finite-state-machines#verze-v-c" class="hash-link" aria-label="Přímý odkaz na Verze v C++" title="Přímý odkaz na Verze v C++" translate="no">​</a></h2>
<p>V C++ je stejný vzor třída. Stav je <code>enum class</code>, rutiny jsou privátní členské funkce a tabulka je <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>Žádost je <code>stateMachine.RequestState(State::Pressed)</code> v rutině <code>CheckLeave</code>. Řádek tabulky musí patřit svému stavu, což se kontroluje už při <strong>překladu</strong> pomocí <code>static_assert</code>, takže chyba z první verze se ani nepřeloží. Není tu halda, výjimky ani RTTI, takže to vyhovuje obvyklým embedded omezením a omezením podobným MISRA. Verze v C++ byla přeložena s <code>-Wall -Wextra -Wconversion -pedantic -fno-exceptions -fno-rtti</code> a běžela pod sanitizery adres a nedefinovaného chování se stejnými scénáři jako verze v C: pořadí volání, žádost, neplatná žádost, poškozený stav a přeskočené rutiny <code>NULL</code>.</p>
<p>Druhá část této série, <a class="" href="https://embedbits.cz/cs/blog/fsm-in-practice-button">tlačítko s debounce a dlouhým stiskem</a>, ukazuje šablonu ve skutečném modulu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="licence">Licence<a href="https://embedbits.cz/cs/blog/finite-state-machines#licence" class="hash-link" aria-label="Přímý odkaz na Licence" title="Přímý odkaz na Licence" 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:encoded>
            <category>Embedded</category>
        </item>
    </channel>
</rss>