<?xml version="1.0" encoding="utf-8"?>
<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>Jeff McBride Blog</title>
        <link>https://jeffmcbride.net/blog</link>
        <description>Jeff McBride Blog</description>
        <lastBuildDate>Fri, 27 Feb 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Rust static init with None]]></title>
            <link>https://jeffmcbride.net/blog/2026/02/27/rust-static-init-with-none</link>
            <guid>https://jeffmcbride.net/blog/2026/02/27/rust-static-init-with-none</guid>
            <pubDate>Fri, 27 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Surprise code bloat]]></description>
            <content:encoded><![CDATA[<p>Today I learned: initializing a rust static with None does NOT ensure a zero initialized variable! </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="static-data-intro">Static data intro<a href="#static-data-intro" class="hash-link" aria-label="Direct link to Static data intro" title="Direct link to Static data intro">​</a></h2><p>I encourage the use of static storage for all of your embedded application data storage. The reason is that then you know pretty well at build time what your RAM usage is and if it will fit, and you have less risk of stack overflow when the stack is used only for small local stuff.</p><p>So, a common pattern is allocating large buffers of data in <code>static</code> variables. However, rust also has some limits on const functionality which can be used for initalization, and some strict rules about uninitialized variables, so a common pattern is to store your static variables in an Option which starts at None, and gets initialized at startup: </p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DATA</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Mutex</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">MyType</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain">  </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Mutex</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="bss-vs-data">BSS vs DATA<a href="#bss-vs-data" class="hash-link" aria-label="Direct link to BSS vs DATA" title="Direct link to BSS vs DATA">​</a></h2><p>A key thing to know is that your static variables can end up in two categories: </p><p>BSS is a section of memory which is zero-ized during the runtime init -- before your application hits main. DATA is a section of memory that get copied into RAM during the runtime init. The key differentiator is that DATA goes into your flash -- it's part of your code size -- while BSS does not. </p><p>Variables which are initialized with ALL zeros go into BSS. Variables which are not, go into DATA. And, there's no splitting up data, or compresssion here. If a struct has a size of 1kB, and one byte in the initial value is non zero, all 1kB will be stored into your flash! This can lead to some surprising code bloat, so it's generally a good idea to try to make sure that your large data types can be zero-initialized where possible. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="is-none-encoded-with-zeros">Is <code>None</code> encoded with zeros?<a href="#is-none-encoded-with-zeros" class="hash-link" aria-label="Direct link to is-none-encoded-with-zeros" title="Direct link to is-none-encoded-with-zeros">​</a></h2><p>If you'd asked me a couple days ago, I'd have said: "yes, I think so!" Now, I know the answer is: "Usually!"</p><p>But today, when I was investigating my code size, I found a surprising large symbol in the data section. The size made sense -- the struct contained about 5kB worth of CAN message buffering -- but it was being initialied with None so why was it going into the <code>.data</code> section?!</p><p>The answer appears to be that None is usually encoded with zeros, but not <em>always</em>. For example, there is an exception when wrapping <code>bool</code> types, which the compiler knows can only have the value of 0 or 1. Since it knows the bool can never be 2, it is free to use the value of 2 as the discriminant for None, and combine the discriminant into the value byte, so it does. This has the benefit that <code>size_of::&lt;Option&lt;bool&gt;&gt;()</code> is 1, just like the <code>bool</code>.  Otherwise, it would have to prepend an extra discriminant in front of the bool value, making the size of the data type larger in memory. </p><p>My struct, in addition to the CAN message buffers, had an array of bools, and so it seems that the compiler re-arranged the ordering of the struct in memory so that the array of bools came first, and then used a value of 2 as the discriminant for the Option enum, and so my entire 5k struct got initialized from <code>.data</code>. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="demo-code">Demo Code<a href="#demo-code" class="hash-link" aria-label="Direct link to Demo Code" title="Direct link to Demo Code">​</a></h2><p>I wrote a quick example to demonstrate the behavior: </p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">core</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">mem</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">size_of</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> transmute</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Foo</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    buf</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">256</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">FooWithBool</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    buf</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">256</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">FooWithBoolArray</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">bool</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    buf</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">256</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FOO</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Foo</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FOO_WITH_BOOL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">FooWithBool</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FOO_WITH_BOOL_ARRAY</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">FooWithBoolArray</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">BOOL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">bool</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FOO_SIZE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">size_of</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Foo</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FWB_SIZE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">size_of</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">FooWithBool</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FWBA_SIZE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">size_of</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">FooWithBoolArray</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">BOOL_SIZE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">size_of</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">bool</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> foo_data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FOO_SIZE</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">unsafe</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">transmute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">FOO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> fwb_data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FWB_SIZE</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">unsafe</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">transmute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">FOO_WITH_BOOL</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> fwba_data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FWBA_SIZE</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">unsafe</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">transmute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">FOO_WITH_BOOL_ARRAY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> bool_data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">BOOL_SIZE</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">unsafe</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">transmute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">BOOL</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Show the first 12 bytes of each</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"size_of Option&lt;Foo&gt;: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FOO_SIZE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"size_of Option&lt;FooWithBool&gt;: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FWB_SIZE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"size_of Option&lt;FooWithBoolArray&gt;: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">FWBA_SIZE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"size_of Option&lt;bool&gt;: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">BOOL_SIZE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"FOO:           {:?}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">foo_data</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"FOO_WITH_BOOL: {:?}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">fwb_data</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"FOO_WITH_BOOL_ARRAY: {:?}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">fwba_data</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"BOOL: {:?}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> bool_data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>You can also run this yourself on the <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2024&amp;gist=24f8ec1501a93c7bff413825b5345b13" target="_blank" rel="noopener noreferrer">Rust Playground</a></p><p>The ouput? </p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">size_of Option&lt;Foo&gt;: 1024</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">size_of Option&lt;FooWithBool&gt;: 1028</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">size_of Option&lt;FooWithBoolArray&gt;: 1028</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">size_of Option&lt;bool&gt;: 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">FOO:           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">FOO_WITH_BOOL: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">FOO_WITH_BOOL_ARRAY: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BOOL: [2]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>As you can see, with a plain bool, you get a non-zero encoding, as with the array of bools. A single bool in the struct does NOT result in non-zero None encoding, I think because it had to pad the bool anyway, so the 3 extra padding bytes can be used to store the discriminant. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-solution">The solution<a href="#the-solution" class="hash-link" aria-label="Direct link to The solution" title="Direct link to The solution">​</a></h2><p>The only reliable solution I can think of to ensure a static var initializes with 0 is to use <a href="https://doc.rust-lang.org/std/mem/union.MaybeUninit.html" target="_blank" rel="noopener noreferrer"><code>MaybeUninit</code></a>. </p><p>The <a href="https://docs.rs/static_cell/latest/static_cell/index.html" target="_blank" rel="noopener noreferrer"><code>static_cell</code> crate</a> handles this well for you when you just need a local <code>&amp;mut</code>. It will not really help you share the static with an IRQ.</p>]]></content:encoded>
            <category>embedded</category>
            <category>rust</category>
        </item>
        <item>
            <title><![CDATA[2025 Book Reviews]]></title>
            <link>https://jeffmcbride.net/blog/2025/12/30/2025-book-reviews</link>
            <guid>https://jeffmcbride.net/blog/2025/12/30/2025-book-reviews</guid>
            <pubDate>Tue, 30 Dec 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>With 2025 coming to a close, I'm going through the annual tradition of reflecting on, and summarizing the
year. One of the things I'm reviewing is my reading log, so here's a few of the books I read this year
that most standout in my memory. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-bobiverse-series">The Bobiverse Series<a href="#the-bobiverse-series" class="hash-link" aria-label="Direct link to The Bobiverse Series" title="Direct link to The Bobiverse Series">​</a></h2><div style="text-align:center;align-content:center;padding-bottom:1.5em"><div data-rmiz-wrap="visible"><img src="/assets/images/we_are_legion-17b53080b5ae93774f504896e2dac803.png" alt="We are Legion cover" width="250px"><button aria-label="Zoom image" data-rmiz-btn-open="true"></button></div></div><p>A 5-book series by Dennis E. Taylor.</p><p>This is almost certainly the most fun read on this list. I bought the first book on a recommendation
from my brother, and then went through all five books over the next couple months. It's a light, somewhat
corny sci-fi story based on a formerly-human "replicant" named Bob -- his mind uploaded onto some
specialized hardware, he's sort of an AI with human memories -- who is placed in command of a
self-reproducing Von Neumann probe and sets off to explore the galaxy. Over the centuries, he ends
up building a whole new post-organic civilization. </p><p>Apparently, book 6 <a href="http://dennisetaylor.org/status-of-things/" target="_blank" rel="noopener noreferrer">is coming</a>, and I look forward to it.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-control-of-nature">The Control of Nature<a href="#the-control-of-nature" class="hash-link" aria-label="Direct link to The Control of Nature" title="Direct link to The Control of Nature">​</a></h2><div style="text-align:center;align-content:center;padding-bottom:1.5em"><div data-rmiz-wrap="visible"><img src="/assets/images/control_of_nature-f22894977247c4effa13e39596cb20b4.jpg" alt="Control of Nature cover" width="250px"><button aria-label="Zoom image" data-rmiz-btn-open="true"></button></div></div><p>This is a book of three journalistic essays by John McPhee, published in 1989. </p><p>The essays are: </p><ol><li>A story of the Army Corp of Engineers and it's struggles to keep the Mississippi river on its course. </li><li>The 1973 Heimaey eruption in Iceland, and how a ragtag team worked to aquire every pump they could to move enough sea-water to redirect the lava flows and save the harbor. </li><li>Debri flows in the San Gabriel mountains around Los Angeles, and the cities struggle to contain them</li></ol><p>The Icelandic eruption was my favorite. The stories of walking, driving bull dozers, and keeping hoses running across the barely solidified lava fields as things spontaneously caught on fire and lava bombs fell from the sky are great. I ended up visiting Iceland shortly after reading it, and was disappointed I didn't have time to take the ferry to the island where it took place. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-nvidia-way">The Nvidia Way<a href="#the-nvidia-way" class="hash-link" aria-label="Direct link to The Nvidia Way" title="Direct link to The Nvidia Way">​</a></h2><div style="text-align:center;align-content:center;padding-bottom:1.5em"><div data-rmiz-wrap="visible"><img src="/assets/images/the_nvidia_way-cda3aebb1aa4e07472a524ab2c925877.jpg" alt="The Nvidia Way cover" width="250px"><button aria-label="Zoom image" data-rmiz-btn-open="true"></button></div></div><p>A profile of Jensen Huang and the rise of Nvidia by Tae Kim. I found this to be a very well written
book filled with interesting details and stories. I think this kind of book can easily be very
boring, but this one really held my attention, and I learned some things.</p>]]></content:encoded>
            <category>books</category>
        </item>
        <item>
            <title><![CDATA[Adding PDO Defaults to zencan]]></title>
            <link>https://jeffmcbride.net/blog/2025/12/28/pdo-defaults</link>
            <guid>https://jeffmcbride.net/blog/2025/12/28/pdo-defaults</guid>
            <pubDate>Sun, 28 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The simple feature that wasn't]]></description>
            <content:encoded><![CDATA[<p>Adding a simple feature to zencan brought up some thorny topics.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-original-problem">The original problem<a href="#the-original-problem" class="hash-link" aria-label="Direct link to The original problem" title="Direct link to The original problem">​</a></h2><p>In zencan, objects have a default value. Of course they do -- they have to start with something!
Often times that's just 0, but some objects should be initialized with particular values. For
"application objects" -- the custom objects created in the application-specific "device config" file
-- the default value can be specified as part of the object definition. However, some objects are
defined automatically for the application by the code generation system, including the PDO
configuration objects. Until just recently, there wasn't any way to specify the defaults for these. </p><p>PDO config objects (there are two for each PDO, called the "comm", and "mapping" objects) control how
PDO messages are sent and received, and which data objects the PDO payload bytes are mapped to. Up
to now, I've configured PDOs by writing to the comm and mapping objects via the SDO server, and then
saving those values to flash. That's great and this type of run-time configurability is a key
motivator for the project, but for some applications it makes a lot of sense to boot up with
pre-configured PDOs, and so zencan needed a mechanism to specify defaults.</p><p>So, easy enough: I'll add some attributes in the <code>[pdos]</code> section of the device config to set the
defaults, I figured. I already have a schema used in the "node configuration" files, which are used
by zencan-client to do the run-time configuration. It looks like this: </p><div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Configure TPDO1 to send on CAN ID 0x200</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[tpdo.1]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">enabled = true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cob = 0x200</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">transmission_type = 254</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Fill the PDO data with 4 bytes from object 0x2000sub1 and 4 more from 0x2000sub2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mappings = [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    { index=0x2000, sub=1, size=32 },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    { index=0x2000, sub=2, size=32 },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>"This will be quick and easy", I figured. It was not. </p><p>Objects in zencan are defined as static variables in generated code. Then references to all the
objects are put into a list of <code>ODEntry</code> objects. It looks something like this: </p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RPDO_COMM_OBJECTS</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">PdoCommObject</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1usize</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">PdoCommObject</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">NODE_STATE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpdos</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0usize</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">OBJECT1000</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Object1000</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Object1000</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">OBJECT1001</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Object1001</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Object1001</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">OD_TABLE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">ODEntry</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3usize</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ODEntry</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        index</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0x1000</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">OBJECT1000</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ODEntry</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        index</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0x1001</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">OBJECT1001</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ODEntry</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        index</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0x1400</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">RPDO_COMM_OBJECTS</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0usize</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Defaults are just rust initializers. And this is where the first issue popped up. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="non-const-init">Non-const init<a href="#non-const-init" class="hash-link" aria-label="Direct link to Non-const init" title="Direct link to Non-const init">​</a></h2><p>The first problem you hit here is that when you write to the mapping object, you write a u32
referencing the object-to-be-mapped by index and sub-index. But what the PDO actually stores is a
reference to the object, so that it doesn't have to search through the table every time it has to
load/store data. The data stored for each mapping looks like this:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/// Data structure for storing a PDO object mapping</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">MappingEntry</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// A reference to the object which is mapped</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> object</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'static</span><span class="token plain"> </span><span class="token class-name">ODEntry</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'static</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// The index of the sub object mapped</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> sub</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// The length of the mapping in bytes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> length</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Strictly speaking, the code generation "knows" the name and ID of every object, so it could
probably generate const MappingEntry objects with the correct static references. But this is going
to really complicated the already too complicated code generation code, and also yet another
datatype that should be private has to become public, because the generated code now has to know
more about the internals of the PDO object implementation. </p><p>But there's a bigger reason this isn't worth pursuing: Eventually zencan needs to support restoring
defaults at run-time for all objects. So objects need to store a live working value as well as the
default value for re-initializing.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="duplicating-memory">Duplicating memory<a href="#duplicating-memory" class="hash-link" aria-label="Direct link to Duplicating memory" title="Direct link to Duplicating memory">​</a></h2><p>This raises a new concern: to restore at default, there is a requirement that both the default value
and the live value be stored somewhere. But, ideally, the default value will be stored exactly once,
and only in flash, while the live value will also be stored exactly once, and in RAM. </p><p>This led down a new rabbit hole of testing what scenarios rust will place data into the
<code>data</code> section vs <code>bss</code>. The <code>data</code> section is part of the program flash size and static RAM
allocation -- it is copied to RAM to initialize the variables. The bss section is just zero'd, so it
doesn't have corresponding bytes in flash, making the program size smaller. In order for an object
to live in <code>bss</code>, it needs to be initialized with all zeros. Incidentally, if one of the attributes of
your object is a reference, it cannot be initialized with zeros. </p><p>There are other concerns, like in the case of PDOs, they have to allocate RAM storage for the
maximum allowed number of mappings, but in flash, it would be better if the defaults were stored as
variably-sized slices, so only the number of mappings initialized in the default have to take up
program space. </p><p>I suspect that in the future, this will be revisted, and I think the path is going to be to enforce
that the object and the object dict are private and can only be accessed via a getter function which
can ensure a one-time lazy initialization process is observed. This will allow things like
<code>MaybeUnininit&lt;&amp;'static Pdo&gt;</code> where needed, to ensure that objects can go into BSS. </p><p>But as spun in a few circles on this, I realized that I was falling into a classic scope creep trap
that I am very susceptible to: instead of finishing the PDO default feature I set out to implement I
was refactoring all object initialization which could better be done in a follow-on PR. So I'm
leaving this for later, and accepting that the first pass at PDO defaults may use more flash bytes
than strictly necessary. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="defaults-as-a-function-of-runtime-state">Defaults as a function of runtime state<a href="#defaults-as-a-function-of-runtime-state" class="hash-link" aria-label="Direct link to Defaults as a function of runtime state" title="Direct link to Defaults as a function of runtime state">​</a></h2><p>It is standard in CANOpen devices for the default PDO COB IDs to be based on the configured node ID,
e.g. <code>$NODEID+0x180</code>. This makes a lot of sense: you might have a device that puts out some PDOs by
default, and you might put more than one of those devices on the network, so zencan should support
this! This means that the default we wish to load isn't even known at compile time. </p><p>Also! The main unit of information is the object data -- i.e. the bytes stored in the objects. This
is what remote clients can access via the SDO server, and this is what is stored in flash when
settings are persisted. So lets say our node ID is 1 and the default initializer has set the COB ID
to 0x181. Now, lets say we save all the objects to flash. Then we change the node ID to 2 and reset.
Should the new COB ID be 0x182? That's what I would expect! The user never changed it from the
default, which is <code>$NODEID+0x180</code>, and now <code>$NODEID=2</code>, so <code>0x182</code>. But what we read from flash for
the COMM object is <code>0x181</code>. Did the user write this value, or was it a default calculation? We now
have to somehow distinguish these cases. </p><p>We could track whether the default COMM value has been changed, and then skip storing it to flash if
it has not been changed from the default. That would help. But as things are setup currently, the
object can't distinguish between a default being written and a value written from e.g. an SDO
client. </p><p>Speaking of SDO clients: ideally, when they read the PDO configuration they could tell the
difference between a COB ID which is set to <code>0x181</code> and a COB ID which is set to <code>$NODEID+0x180</code>.
<em>Ideally</em> they'd even be able to configure a COB ID to use a node ID offset at runtime. If I was
designing this protocol, I'd put a flag in the PDO COMM object called <code>add_node_id</code> to control this
behavior so that the state is encoded in the object.</p><p>As I have done before when I have found the CANOpen protocol confounding, I went and and looked at
what the most popular C implementation does (<a href="https://github.com/CANopenNode/CANopenNode/blob/master/301/CO_PDO.c#L679" target="_blank" rel="noopener noreferrer">relevant file</a>).</p><div class="language-C codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-C codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/* if default CAN-ID is written, store to OD without Node-ID */</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if (CAN_ID == PDO-&gt;preDefinedCanId) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    (void)CO_setUint32(bufCopy, COB_ID &amp; 0xFFFFFF80U);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-C codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-C codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/* If default CAN-ID is stored in OD (without Node-ID), add Node-ID */</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if ((CAN_ID != 0U) &amp;&amp; (CAN_ID == (preDefinedCanId &amp; 0xFF80U))) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    CAN_ID = preDefinedCanId;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>To understand the above snippets, you should know that (sticking with <code>$NODEID=1</code> and
<code>COB_ID=$NODEID + 0x180</code> as an example) <code>preDefinedCanId</code> is set to 0x181.  If the value encoded in
the object is <code>0x180</code>, it always adds the node id. If a user writes <code>0x181</code>, it assumes that what
the user really meant was <code>$NODEID + 0x180</code> and stores <code>0x180</code> to the object. So if I try to write
0x181, it gets converted to 0x180. And when the stored value is 0x180, that is interpreted as the
default <code>$NODEID+0x180</code>. </p><p>I don't love this. It's a <em>special rule</em>, and it's a <em>surprising behavior</em>. It also makes it
impossible to use 0x180 as a COB ID, or to set the COB ID to <code>0x181</code> irrespective of the node ID. If
I write 0x181 to the COB ID, I expect that to be the new COB ID even if I change the node ID. It's
not hard to come up with a use case where this actually becomes a problem: </p><p>Imagine some device expects a particular message on 0x181 because historically it was sent by node 1
using the default. I come along and decide that I'm going to manage my network by serial number,
and I don't care about what node IDs are assigned, so I write a controller which enumerates the
nodes via LSS, and assigns them arbitrary IDs, but loads configurations into each node based on
serial number. I want a node with a particular serial number to send the 0x181 PDO, so I set it up
that way, only to find that when assigned a random node ID it is suddenly sending the PDO <em>on a
different ID!</em>. </p><p>Also I think ideally it should be possible to set <em>default</em> PDO IDs which do not have the node ID
added. A realistic use case is: "this type of device always sends this message, regardless of the
assigned node ID". But this precludes any default initialization scheme which is limited to
restoring object values, because the answer to the question "should I add the node ID" is not
encoded anywhere in the object values. This is the same situation I'm sure the CANOpenNode author(s)
were faced with when they decided to enact the special rules above. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="options">Options<a href="#options" class="hash-link" aria-label="Direct link to Options" title="Direct link to Options">​</a></h2><p>Once again I am tempted to throw out the CANOpen spec and go my own way, but I'm not quite there
yet. Some options considered:</p><ol><li>Use COB_ID=0 as a special value indicating to use the default. The default has to be stored
outside of the object data, and serialization to persistent storage has to be prevented when the
value is 0 (because serializing just reads the object, and reading the object returns the computed
value).</li><li>Adopt the special rules of CANOpenNode.</li><li>Drop support for adding node ID to PDO IDs altogether.</li><li>Add a new sub object to the PDO comm object to store a flag for "add the node ID" behavior.</li></ol><p>I think 4 is clearly the ideal. Doing anything else feels like I am compromising for the sake of an
old protocol, but also, if I add a sub object then someone, someday is going to use zencan to try to
do a CANOpen compliance certification and will fail and be annoyed with me. </p><p>Number 2 and 3 I think are non-starters. The NODE ID offsets are standard and useful, and the
special rules of number 2 are just too weird of a corner case for my taste. </p><p>So number 1 seems like the most plausible. It allows assigning any ID to the PDO via SDO, and it
allows defaults to include the node ID or not. It does not allow an SDO client to distinguish
between default and non-default state in general, and it does not allow setting arbitrary <code>$NODEID + x</code>
values for the COB ID, but this is not an immediate problem at least. Also, I think it is still
relatively easy in the future to add an optional extension sub-object to the COMM object with the
<code>add_node_id</code> flag if the need ever really does arise.</p>]]></content:encoded>
            <category>zencan</category>
            <category>embedded</category>
            <category>rust</category>
        </item>
        <item>
            <title><![CDATA[Publishing zencan crates]]></title>
            <link>https://jeffmcbride.net/blog/2025/10/29/zencan-crates-published</link>
            <guid>https://jeffmcbride.net/blog/2025/10/29/zencan-crates-published</guid>
            <pubDate>Wed, 29 Oct 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>I've finally published v0.0.1 of zencan to crates.io.</p><p>After a big push back in June to get to something that more or less worked, I published
<a href="/blog/2025/06/05/introducing-zencan">zencan</a> on github and then proceeded to lose momentum for a
while. My attention wandered to other things, and I've been traveling a lot. But in the meantime, it
has been out there, and I can tell that at least a few people have been trying to use it, because
some of them have reached out to me about it. The project even picked up a second contributor:
Ettiene <a href="https://github.com/mcbridejc/zencan/pull/22" target="_blank" rel="noopener noreferrer">provided some examples for the esp32</a>, as well
as fixing some bugs. I can also see from the search traffic that people are out there searching for
"rust canopen". All of this is good motivation to put more work into the project.</p><p>I put off publishing the crates initially because I was hoping to resolve some changes to a
dependency I had forked. After radio silence from the maintainer<sup id="fnref-1-719674"><a href="#fn-1-719674" class="footnote-ref">1</a></sup>, I ended up <a href="https://github.com/mcbridejc/zencan/pull/25" target="_blank" rel="noopener noreferrer">working around
that</a> easily enough. Beyond that, it has just been a
nagging sense of perfectionism -- there are more features I should implement or better docs to write
before it was worth publishing a crate. Somehow pushing the crate feels more symbolic than throwing
some code onto a github repo. It feels like more of a statement that "this is actually good enought to
use".</p><p>But I decided it will be fine, and I think the practice of releases, writing changelogs, considering
breaking changes more, etc will be good for the process.</p><p>Also! The timing is good now because rust v1.90 stabilized <a href="https://github.com/rust-lang/cargo/pull/15636/" target="_blank" rel="noopener noreferrer">multi package
publishing</a>! One of the authors of this feature
wrote a <a href="https://www.tweag.io/blog/2025-07-10-cargo-package-workspace/" target="_blank" rel="noopener noreferrer">good blog post</a> about it.
Zencan is broken up into many crates, so this made the releasing process a lot easier. </p><p>Now there are more features to work on. Top of the probable list are: </p><ul><li>CAN-FD support</li><li>Refactoring the device config / object dictionary management code, and adding EDS export</li><li>SDO Client Updates<ul><li>blocking client support</li><li>no_std client support</li></ul></li><li>SYNC support (client and node)</li></ul><div class="footnotes"><hr><ol><li id="fn-1-719674">Not trying to throw any shade. I have been in that position, and will likely be again.
Publishing some open source code doesn't obligate someone to support it for randos like me forever.<a href="#fnref-1-719674" class="footnote-backref">↩</a></li></ol></div>]]></content:encoded>
            <category>zencan</category>
            <category>embedded</category>
            <category>rust</category>
        </item>
        <item>
            <title><![CDATA[Building an application for the CoreMP135 using Rust and Slint]]></title>
            <link>https://jeffmcbride.net/blog/2025/10/27/building-a-rust-application-for-the-coremp135-using-slint</link>
            <guid>https://jeffmcbride.net/blog/2025/10/27/building-a-rust-application-for-the-coremp135-using-slint</guid>
            <pubDate>Mon, 27 Oct 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>This is a followup to <a href="/blog/2025/10/25/coremp135-linux-device-buildroot/">Creating linux images for the M5Stack CoreMP135 with
Buildroot</a>. The last post talked about using
buildroot to make a linux image, and this post is about building an application in Rust and running
it on the image. The demo application is a CAN logger. It will use Slint to create a simple UI on
the touchscreen to start and stop the log file, and it will log data to an exFAT partition on the
microSD card. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="getting-code-onto-the-device">Getting code onto the device<a href="#getting-code-onto-the-device" class="hash-link" aria-label="Direct link to Getting code onto the device" title="Direct link to Getting code onto the device">​</a></h2><p>If you successfully built an image using
<a href="https://github.com/mcbridejc/coremp135-bsp" target="_blank" rel="noopener noreferrer"><code>coremp135-bsp</code></a>, and you added your key to the
<code>authorized_keys</code> file on the target, you should be able to SSH to it by connecting to ETH1 and using the static IP configured on it -- <code>192.168.2.254</code>, or whatever you customized it
to.</p><p>Then you can copy files to it with scp, e.g. <code>scp -O my_file root@192.168.2.254:/root/</code>. </p><p>I like to add the following entry to <code>~/.ssh/config</code> to simplify connecting: </p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">host coremp135</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    HostName 192.168.2.254</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    StrictHostKeyChecking no</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    UpdateHostkeys yes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    User root</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>From here on out, you may see me reducing transfers to <code>scp -O my_file coremp135:/root/</code>; this is
why.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="cross-compiling">Cross Compiling<a href="#cross-compiling" class="hash-link" aria-label="Direct link to Cross Compiling" title="Direct link to Cross Compiling">​</a></h2><p>First of all, lets just get Hello World building. </p><p>Create a new project: <code>cargo init</code></p><p>Add a <code>rust-toolchain.toml</code> file with the following:</p><div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">[toolchain]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">channel = "1.90.0"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">targets = [ "armv7-unknown-linux-gnueabihf" ]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">profile = "default"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>And, we'll go ahead and add the <code>linuxfb</code> dependency -- we're going to it later, and it is going to be using bindgen, and will require some header files from the buildroot system, so lets get it compiling now too. </p><p><code>cargo add linuxfb</code></p><p>Now you can build for the arm target with the following command, but it will fail! </p><p><code>cargo build --release --target=armv7-unknown-linux-gnueabihf</code></p><p>We need to use the linker from buildroot, which is setup in <code>.cargo/config.toml</code>:</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># .cargo/config.toml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[target.armv7-unknown-linux-gnueabihf]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">linker = "arm-buildroot-linux-gnueabihf-gcc"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Great. Now building will fail differently! </p><p>We're going to be setting up some environment variables, to get that linker in our path and also to
setup some options for sysroots. The extra options aren't necessary if we are building pure rust,
but when you link against shared libraries, or compile C code (e.g. with bindgen/clang) during the
build, you likely will need them. I put these environment variables into <code>.envrc</code>, so they can be
used with tools like <a href="https://direnv.net" target="_blank" rel="noopener noreferrer">direnv</a>, but they can also be activated in your current shell by
simply sourcing the file: <code>. ./.envrc</code>. </p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># .envrc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># The directory where host binaries are stored in `/bin`, and the sysroot is stored in</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># `arm-buildroot-linux-gnueabihf/sysroot`. This can be `output/host` in a buildroot working</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># directory, or an SDK tarball built using `make sdk`</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BUILDROOT_SDK_RELATIVE="../buildroot/output/host"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Paths have to be absolute, because crates will build with different working directories</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export BUILDROOT_SDK=$(cd "$BUILDROOT_SDK_RELATIVE"; pwd -P)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export SYSROOT=$BUILDROOT_SDK/arm-buildroot-linux-gnueabihf/sysroot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export PKG_CONFIG_SYSROOT_DIR=$SYSROOT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export PKG_CONFIG_PATH=$SYSROOT/usr/lib/pkgconfig/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># We need the linker (`arm-buildroot-linux-gnueabihf-gcc`) from buildroot in the path. But buildroot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># also builds a host rustc, and this will override the cargo installed rust toolchain unless we output</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># cargo into path ahead of it</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export PATH=$HOME/.cargo/bin:$BUILDROOT_SDK/bin:$PATH</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Bindgen is used by some lib crates, like linuxfb, and it needs to know where sysroot is as well</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export BINDGEN_EXTRA_CLANG_ARGS_armv7_unknown_linux_gnueabihf="--sysroot $SYSROOT"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>You can generate a tarball with all of the required sysroot files from buildroot using the <code>make
sdk</code> target, and I do recommend doing this and saving the tarball once your linux system is somewhat
stable. </p><p>Now hopefully, your program builds. You can transfer it to the target using scp, then login and run it:</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">scp -O target/armv7-unknown-linux-gnueabihf/release/demo coremp135:/root  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ssh coremp135</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># ./demo </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Hello, world!</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="building-a-ui">Building a UI<a href="#building-a-ui" class="hash-link" aria-label="Direct link to Building a UI" title="Direct link to Building a UI">​</a></h2><p>The touchscreen can be used by drawing to the frame buffer at <code>/dev/fb1</code>, and reading input events
from <code>/dev/input/event0</code>. </p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="rendering">Rendering<a href="#rendering" class="hash-link" aria-label="Direct link to Rendering" title="Direct link to Rendering">​</a></h3><p>For this, we're going to use <a href="https://slint.dev" target="_blank" rel="noopener noreferrer">Slint</a> to build the UI. You can use tools like the <a href="https://marketplace.visualstudio.com/items?itemName=Slint.slint" target="_blank" rel="noopener noreferrer">Slint vscode plugin</a> or <a href="https://slintpad.com" target="_blank" rel="noopener noreferrer">SlintPad</a> to design the slint file, and it has good support for embedded devices (although note the licensing for commercial products). Of course, any UI library capable of drawing pixels to a frame buffer will work here too!</p><p> We'll use the Slint <a href="https://docs.slint.dev/latest/docs/rust/slint/platform/software_renderer/" target="_blank" rel="noopener noreferrer">software
renderer</a> and the
<a href="https://crates.io/crates/linuxfb" target="_blank" rel="noopener noreferrer">linuxfb crate</a> crate to draw to the screen in our own event loop. </p><p>The minimum test application to render a slint UI looks like this: </p><p>First, add the following dependencies to <code>Cargo.toml</code>:</p><div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">[dependencies]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">linuxfb = "0.3.1"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">slint = { version = "1.13.1", default-features = false, features = ["renderer-software", "std", "compat-1-2"] }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[build-dependencies]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">slint-build = "1.13.1"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Then, add a simple .slint file to define the UI in <code>ui/touch.slint</code>:</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">import { AboutSlint, Button, VerticalBox } from "std-widgets.slint";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">export component Demo inherits Window {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    VerticalBox {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        alignment: start;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        Text {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            text: "Hello World!";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            font-size: 24px;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            horizontal-alignment: center;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        AboutSlint {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            preferred-height: 150px;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        HorizontalLayout { alignment: center; Button { text: "OK!"; } }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Then add a <code>build.rs</code> to compile your UI at build-time:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// build.rs</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">slint_build</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">compile_with_config</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"ui/touch.slint"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">slint_build</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">CompilerConfiguration</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">embed_resources</span><span class="token punctuation" style="color:#393A34">(</span><span class="token namespace" style="opacity:0.7">slint_build</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">EmbedResourcesKind</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">EmbedForSoftwareRenderer</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Then, in the application: </p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// main.rs</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token namespace" style="opacity:0.7">rc</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Rc</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">time</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Instant</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">slint</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">platform</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token namespace" style="opacity:0.7">software_renderer</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">MinimalSoftwareWindow</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Rgb565Pixel</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Platform</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">MyPlatform</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    window</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Rc</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">MinimalSoftwareWindow</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    start_instant</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Instant</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">MyPlatform</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">window</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Rc</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">MinimalSoftwareWindow</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">Self</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> start_instant </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Instant</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">Self</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            window</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            start_instant</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">Platform</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token class-name">MyPlatform</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">create_window_adapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Rc</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">dyn</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">slint</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">platform</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">WindowAdapter</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">slint</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">PlatformError</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">clone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">duration_since_start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">core</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">time</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Duration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">start_instant</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">elapsed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Include the types created by slint in build.rs</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token namespace" style="opacity:0.7">slint</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token macro property" style="color:#36acaa">include_modules!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// Draw the UI to the framebuffer and exit</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DISPLAY_WIDTH</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">320</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DISPLAY_HEIGHT</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> fb </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">linuxfb</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Framebuffer</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/dev/fb1"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> window </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">MinimalSoftwareWindow</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Default</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">slint</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">platform</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">set_platform</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Box</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MyPlatform</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">clone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token namespace" style="opacity:0.7">slint</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">PhysicalSize</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">320</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 'Demo' is the type exported in touch.slint</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> _ui </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Demo</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> buffer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">Rgb565Pixel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">DISPLAY_WIDTH</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DISPLAY_HEIGHT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">slint</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">platform</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">update_timers_and_animations</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">draw_if_needed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">renderer</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> data </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> fb</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        renderer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DISPLAY_WIDTH</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">unsafe</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token namespace" style="opacity:0.7">core</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">ptr</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">copy_nonoverlapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                buffer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">as_ptr</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">as_mut_ptr</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Run that, and if all goes well, it will draw the UI onto the screen, and quit.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="input-events">Input Events<a href="#input-events" class="hash-link" aria-label="Direct link to Input Events" title="Direct link to Input Events">​</a></h3><p>Now we need to be able to push buttons!</p><p>The <a href="https://crates.io/crates/evdev" target="_blank" rel="noopener noreferrer">evdev crate</a> allows reading touch events from the
touchscreen. The <code>MinimalSoftwareWindow</code> struct provides the
<a href="https://docs.slint.dev/latest/docs/rust/slint/struct.Window#method.dispatch_event" target="_blank" rel="noopener noreferrer"><code>dispatch_event()</code></a>
method for receiving input events. So to build an interactive UI, we just need to create an event
loop: a thread which reads events, passes them to the Window, and then redraws as necessary. The
only thing is, the <code>dispatch_event()</code> method wants to receive a
<a href="https://docs.slint.dev/latest/docs/rust/slint/platform/enum.WindowEvent" target="_blank" rel="noopener noreferrer">`WindowEvent'</a>, so clearly
we need some code to convert the evdev events into these. </p><p>If you are trying to do this...you are in luck! I did it already and published it in the
<a href="https://crates.io/crates/slint-evdev-input" target="_blank" rel="noopener noreferrer">slint-evdev-input</a> crate.</p><p>The code for the entire event loop is getting a little long, so I'm not going to include it here. Instead, <a href="https://github.com/mcbridejc/coremp135-canlogger/blob/1a6c792933f50f8edd5fe80dc8272e6fd508922b/canlogger-external/canlogger/src/ui.rs" target="_blank" rel="noopener noreferrer">check it out in the repo</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="putting-it-all-together">Putting it all together<a href="#putting-it-all-together" class="hash-link" aria-label="Direct link to Putting it all together" title="Direct link to Putting it all together">​</a></h2><p>Now, you can build your linux filesystem with buildroot, and you can compile a rust application,
linking against the SDK/filesystem created by buildroot which will run on your system. But
ultimately, you probably want to combine those steps. </p><p>There's no clear one-right-way here, that I see. One way would be to take the <code>coremp135-bsp</code>
project, clone it, and start modifying it. But I wanted to set it up so that I could re-use a single
BSP with different applications. The method I've arrived at is to create an application repository
and have it pull in the <code>buildroot</code> tree and the <code>coremp135-bsp</code> tree as submodules, then define a second
external tree which ammends the BSP tree to customize the system, and add its own applications. </p><p>IMHO, Buildroot does not exactly shine at this, and this process feels a little brittle. But, it is
the best I've come up with so far. </p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="compiling-outside-of-buildroot-vs-a-package">Compiling outside of buildroot vs a package<a href="#compiling-outside-of-buildroot-vs-a-package" class="hash-link" aria-label="Direct link to Compiling outside of buildroot vs a package" title="Direct link to Compiling outside of buildroot vs a package">​</a></h3><p>You can create your application as a buildroot package, letting the buildroot make system compile
and install it. This is a very typical thing to do. The issues that I ran into were: </p><ol><li>I want to also be able to <code>cargo build</code> + <code>scp</code> during development, so I need to set that up to
link against the buildroot SDK anyway</li><li>The version of the rust toolchain included with buildroot was too old for me, so I preferred to
compile with my own rust toolchain, rather than the one buildroot installs for itself.</li></ol><h3 class="anchor anchorWithStickyNavbar_LWe7" id="build-and-install">Build and Install<a href="#build-and-install" class="hash-link" aria-label="Direct link to Build and Install" title="Direct link to Build and Install">​</a></h3><p>In the end, I have a simple
<a href="https://github.com/mcbridejc/coremp135-canlogger/blob/main/Makefile" target="_blank" rel="noopener noreferrer">Makefile</a> at the top-level of
the project which builds everything. </p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">all: buildroot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">.PHONY: buildroot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">buildroot:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    cd buildroot; \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    make BR2_EXTERNAL=../coremp135-bsp:../canlogger-external coremp135_defconfig; \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    make COREMP135_EXFAT_DATA=1 -j4</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The rust application is built and installed via a <a href="https://github.com/mcbridejc/coremp135-canlogger/blob/main/canlogger-external/board/canlogger/post-build.sh" target="_blank" rel="noopener noreferrer">post-build script</a></p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">set -e </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Build rust application</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">(cd ${BR2_EXTERNAL_CANLOGGER_PATH}/canlogger; source ./.envrc; cargo build --release --target armv7-unknown-linux-gnueabihf)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Copy application to target output directory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cp ${BR2_EXTERNAL_CANLOGGER_PATH}/canlogger/target/armv7-unknown-linux-gnueabihf/release/canlogger $TARGET_DIR/usr/bin/canlogger</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Copy overlay files to target output directory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cp -r ${BR2_EXTERNAL_CANLOGGER_PATH}/board/canlogger/overlay/* $TARGET_DIR</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Copy public key for login</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if [ -e ~/.ssh/id_rsa.pub ]; then</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  mkdir -p $TARGET_DIR/root/.ssh</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  cp ~/.ssh/id_rsa.pub $TARGET_DIR/root/.ssh/authorized_keys</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">fi</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>And this seems to work OK. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="expandable-data-partition">Expandable Data partition<a href="#expandable-data-partition" class="hash-link" aria-label="Direct link to Expandable Data partition" title="Direct link to Expandable Data partition">​</a></h2><p>A nuisance of programming devices with SD cards is that you don't generally know the size of the
flash when you create an image -- more over, you ideally don't want create a 32GB image
file just so you can program a mostly empty partition on a 32GB card. </p><p>My setup has three mountable partitions: </p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">- rootfs A</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">- rootfs B</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">- data</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The two rootfs partitions contain the filesystem, and are used by RAUC for doing updates -- if you
are currently booting from A, then an update will be installed on B and the next reboot will boot
from B. </p><p>The data partition is meant to store data which should not be erased on update. I also like to
create separate filesystems for writing data, because setting things up so that your application
doesn't write to your root filesystem is good for stability.</p><p>During image creation, the data partition is created as the last partition on the card, with a
fixed, relatively small size. But really, I'd like it to be expanded to fill whatever space is
available on the card. This is done in canlogger via an init script. After flashing the card, the
first bootup will see that the partition table is small, and it will expand the partition to the end
of the drive. Since the drive is already mounted as the <code>/</code> drive, a reboot is required to get linux
to reload the partition table, so the script reboots after modifying partitions. Then on the next
boot, it sees that the partition is large, but that the filesystem is still at its original size, so
it resizes the filesystem. This is all handled in the <a href="https://github.com/mcbridejc/coremp135-canlogger/blob/main/canlogger-external/board/canlogger/overlay/etc/init.d/S15resize_data" target="_blank" rel="noopener noreferrer">S15resize_data init
script</a>.</p><h1>Repos</h1><p>All the relevant code is at <a href="https://github.com/mcbridejc/coremp135-canlogger" target="_blank" rel="noopener noreferrer">https://github.com/mcbridejc/coremp135-canlogger</a>. Oh, and it's also
capable of logging two CAN busses to a CSV file on the exFAT partition. Maybe that's useful to
somebody too. </p><p>If you want to build a project based on the CoreMP135 and want help, you can <a href="https://www.relativejump.com" target="_blank" rel="noopener noreferrer">hire
me</a>! I'd love a good reason to design a custom board around the
STM32MP1 or STM32MP2 family, so especially if you are thinking about doing that let's chat.</p>]]></content:encoded>
            <category>coremp135</category>
            <category>embedded</category>
            <category>linux</category>
            <category>buildroot</category>
            <category>rust</category>
        </item>
        <item>
            <title><![CDATA[Creating linux images for the M5Stack CoreMP135 with Buildroot]]></title>
            <link>https://jeffmcbride.net/blog/2025/10/25/coremp135-linux-device-buildroot</link>
            <guid>https://jeffmcbride.net/blog/2025/10/25/coremp135-linux-device-buildroot</guid>
            <pubDate>Sat, 25 Oct 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>This post is about the M5Stack CoreMP135: why I like it, and a tutorial about how to use buildroot
to create a linux image for it. A <a href="/blog/2025/10/27/building-a-rust-application-for-the-coremp135-using-slint">follow-up
post</a> describes how I
create applications with Rust to run on it. </p><p>If you want to build a project based on the CoreMP135 and want help, you can <a href="https://www.relativejump.com" target="_blank" rel="noopener noreferrer">hire
me</a>! I'd love a good reason to design a custom board around the
STM32MP1 or STM32MP2 family, so especially if you are thinking about doing that let's chat. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="about-the-coremp135">About the CoreMP135<a href="#about-the-coremp135" class="hash-link" aria-label="Direct link to About the CoreMP135" title="Direct link to About the CoreMP135">​</a></h2><p>I really like <a href="https://docs.m5stack.com/en/core/M5CoreMP135" target="_blank" rel="noopener noreferrer">this</a> little $75 computer from M5Stack.
It's a nicely packaged, low power, small application processor which can run Linux and has a great
set of IO with good connectors. It also has a small touch screen for a UI. It's like a less
powerful, better packaged Raspberry PI designed for industrial control applications.</p><p><img loading="lazy" alt="M5Stack CoreMP135" src="/assets/images/m5stack_features-e4cd9b0cb63a537a2dc1b06bfcd9f0f9.webp" width="800" height="800" class="img_YgWV"></p><p>It's based on the STM32MP135. I'm a long-time user of the STM32 line of MCUs, and this family is a
great addition to it -- it's an application processor with a peripheral set that feels more like a
microcontroller than e.g. the broadcomm chips you find on a raspberry pi. It's single core, and has
just 512MB of RAM, so it's a lightweight for computational power, but I don't usually need that and
the packaging on this is so much nicer than a raspberry PI with some kluged on extension board to
get the IO you need. It also comes with a DIN rail mount as well as tabs with screw holes for
mounting in your system.</p><p>I first picked it up to replace a raspberry PI I had as a house monitor / control system for a
camper. The raspberry PI had the usual problems: </p><ul><li>Power hungry</li><li>I had to have large USB adapters for CAN and RS485, and I don't
like those hanging off the USB-A ports in a vibration-heavy environment</li><li>Flaky USB drivers that seem to crash every couple weeks, requiring a reboot. </li><li>Needs a 5V regulator</li></ul><p>The M5Stack has: </p><ul><li>2 CAN controllers</li><li>1 RS485</li><li>1 TTL UART</li><li>1 I2C</li><li>2 gigabit ethernets!</li></ul><p>This was perfect for my application, because it lowered the power consumption, runs off the 12V
battery, has a smaller physical footprint, and I could use the integrated RS485 + CAN. The touch
screen was a happy bonus. </p><p><strong>Some things I wish it had</strong>: An on-board eMMC so that I can store the application there while
still having the uSD card for removable storage, and the ability to connect a battery backup for the
RTC to keep time when 12V power is removed. </p><p>I'm happy with it in the camper, and I have already ordered a second and found a use for
it on a client project. It's now one of the things that I always want to have a spare on hand for
when something comes up. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="programming-with-buildroot-linux">Programming with Buildroot Linux<a href="#programming-with-buildroot-linux" class="hash-link" aria-label="Direct link to Programming with Buildroot Linux" title="Direct link to Programming with Buildroot Linux">​</a></h2><p>The hardware is great, but I felt that the buildroot examples from M5Stack left a lot to be desired.
So I built my own buildroot external tree to support the board, and to base my own applications off
of for faster development. So I'm going to walk through what I did to get up and running using
buildroot, and RAUC for OTA updates. </p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="buildroot-vs-debian">Buildroot vs Debian<a href="#buildroot-vs-debian" class="hash-link" aria-label="Direct link to Buildroot vs Debian" title="Direct link to Buildroot vs Debian">​</a></h3><p>M5Stack does provide a debian image you can load, and start using this like a normal linux machine,
SSHing in and installing packages with apt. I threw this right out. I don't want to treat this like
a server, I want to treat it like a microcontroller. This means I want a build process to create a
complete image, and I want that image to be as small as possible. I also want the system to be
stripped down to just what I need, because that's good for stability. I also want to support
over-the-air updates, so it's easier to ship new code to the controller. </p><p>There are basically two common ways to build an embedded linux image:
<strong>buildroot</strong> and <strong>yocto</strong>. I don't have a strong argument for one over the
other, but I have a lot more experience with buildroot, and that is what M5Stack
used for their example, so that is what I used. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="buildroot-basics">Buildroot Basics<a href="#buildroot-basics" class="hash-link" aria-label="Direct link to Buildroot Basics" title="Direct link to Buildroot Basics">​</a></h2><p>The way buildroot works is: you checkout the buildroot repository, you configure it (e.g. you can
start with <code>make menuconfig</code>, but more likely you start with a defconfig from somewhere else, more
on that later), and then you build it. It will go and download tarballs of all the components you
enabled -- this is things like the linux kernel and u-boot, as well as utilities for your file
system like busybox and an ssh server. It's all the packages that make up a functioning linux
system. It puts all these together into an image which you can load onto your flash device through
a wildly convoluted series of makefiles and bash scripts. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-the-buildroot-tree">Get the buildroot tree<a href="#get-the-buildroot-tree" class="hash-link" aria-label="Direct link to Get the buildroot tree" title="Direct link to Get the buildroot tree">​</a></h2><p>I started with the <code>st/2024.02.9</code> branch of the <a href="https://github.com/bootlin/buildroot/tree/st/2024.02.9" target="_blank" rel="noopener noreferrer">bootlin buildroot
fork</a>. This does not appear to have a lot of
changes from the <a href="https://github.com/buildroot/buildroot/tree/2024.02.9" target="_blank" rel="noopener noreferrer">mainline buildroot</a>, and the
changes seem to be related to trusted-firmware-m, which I don't think is relevant to the STM32MP135,
so I think I could have just used the mainline buildroot. But I haven't it, so I'm not 100% sure.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-br2-external-tree">The BR2 External Tree<a href="#the-br2-external-tree" class="hash-link" aria-label="Direct link to The BR2 External Tree" title="Direct link to The BR2 External Tree">​</a></h2><p>A typical way to customize a buildroot system is to create a <a href="https://buildroot.org/downloads/manual/manual.html#outside-br-custom" target="_blank" rel="noopener noreferrer">"br2 external
tree"</a>. This can contain your
own configuration, filesystem overlay, device trees, custom packages, etc. </p><p>Bootlin maintains an example BR2 external tree for the whole STM32MP1 family
<a href="https://github.com/bootlin/buildroot-external-st/" target="_blank" rel="noopener noreferrer">here</a>. It's really close, but you can't use this
as-is for the CoreMP135 because it is based on dev boards which have different hardware, different
pinouts, etc. The changes require, at minimum, some modification to device trees.</p><p>M5stack published their own fork of this for the CoreMP135
<a href="https://github.com/m5stack/CoreMP135_buildroot-external-st/" target="_blank" rel="noopener noreferrer">here</a>. I wish they'd cleaned it up a
bit -- e.g. by removing all of the dev board defconfigs, device trees, etc, to focus on the
CoreMP135. You can build a filesystem from this, but I felt it was worth the time to dig into it and
identify the important changes, prune the noise, and integrate it all into my own "board support
package". </p><p>I spent a fair amount of time parsing the changes and integrating into my own config, and I think it
was worth it because I understand much better what's going on, and now I have support for RAUC,
examples of using the touchscreen, and a nice starting point for future projects on the CoreMP135. I
spun up a new application last week for a client and it only took 1.5 days of work, because I could
focus on building the new touch UI and application logic, and didn't have to think much at all about
the underlying system configuration. </p><p>I'm using kernel v6.1. This is still fairly old (December 2022), and maybe one day I will take on
updating to a more recent kernel. The bootlin external tree is using kernel v6.6 (October 2023), so
there's probably no reason I can't use at least that. But there are patches that may be affected,
and often there are device tree schema changes between kernel versions, so updating is not
necessarily trivial. For now v6.1 is getting the job done and there are other things to do.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="touchscreen-issues">Touchscreen issues<a href="#touchscreen-issues" class="hash-link" aria-label="Direct link to Touchscreen issues" title="Direct link to Touchscreen issues">​</a></h2><p>There are a collection of patches provided in the M5Stack BR2 external examples for the ILI9342C
display, and for the backlight which is controlled by an AXP2101 power management IC. M5Stack provides two board configurations: </p><ul><li><code>coremp135</code> with kernel v6.1</li><li><code>coremp135_5_15</code> with kernel v5.15</li></ul><p>A major change between these two kernels is the implementation of the Direct Rendering Manager (DRM)
subsystem for displays. On the 5.15, the LCD driver creates a framebuffer at <code>/dev/fb1</code> and I found
drawing to the display to be as simple as writing pixel data to this framebuffer. However, on the
v6.1 kernel, the LCD is implemented as a TinyDRM device. Luckily, the DRM system does support the
legacy frame buffer interface as well, but I found it did not work! After a log of digging and
learning, I realized that the DRM pipeline was not being enabled, and the way I ended up enabling it
is by installing modetest and running that. To add the modetest executable to the system, you need
the right libdrm packages installed: </p><div class="language-conf codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-conf codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_LIBDRM=y</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_LIBDRM_HAS_ATOMIC=y</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_LIBDRM_INSTALL_TESTS=y</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Then, I just added modetest to rc.local so it is run at boot. This was a huge time sink for me, and
one of the reasons I became frustrated with the M5Stack examples -- the examples just do not seem to
work on the <code>coremp135</code> defconfig from the M5Stack repo. I suspect there is a more straightforward
way to enable the pipeline via libdrm, but I haven't dug into that yet. </p><p>The backlight can be controlled easily via sysfs, by writing a number to
<code>/sys/class/backlight/axp2101_m5stack_bl/brightness</code>, e.g.: </p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"100"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /sys/class/backlight/axp2101_m5stack_bl/brightness</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="rauc-for-ota">RAUC for OTA<a href="#rauc-for-ota" class="hash-link" aria-label="Direct link to RAUC for OTA" title="Direct link to RAUC for OTA">​</a></h2><p>Another problem to tackle was setting up RAUC for over-the-air updates. There are a lot of different
config options, and a lot of things that have to be setup just right to get everything working.</p><p>The way I set it up is that the bundle always includes the entire filesystem, including linux and
the application -- an alternative is that you can also set up separate bundles for the filesystem
and the application, so that application updates can be smaller when they don't require any changes
to the main system. There are two rootfs partitions (A and B), so that if a programming of one
fails, it can fall back to booting from the previous version. There is also a third and separate
data partition, which can be used to store data that does not get erased during updates. </p><p>RAUC requires communication between u-boot and linux, because ultimately it is u-boot which has to
decide which partition to boot from. The communication is done via a shared section of flash which
stores the "u-boot env". In the file <code>stm32mp13_defconfig</code> from the STMicro version of the u-boot tree, you can find the value of
<a href="https://github.com/STMicroelectronics/u-boot/blob/v2022.10-stm32mp/configs/stm32mp13_defconfig#L5" target="_blank" rel="noopener noreferrer"><code>CONFIG_ENV_OFFSET</code> defined as
<code>0x900000</code></a>,
or you can once you've searched enough! This is there u-boot will look for its environment. There is also a second offset, <code>CONFIG_ENV_OFFSET_REDUND</code>, for a redundant copy of the env. Why is the env stored 9MB into the SD card? I've certainly no idea; I guess someone decided that would allow enough space to store the FSBL images before it. </p><p>So, when creating the final image file using <a href="https://github.com/pengutronix/genimage" target="_blank" rel="noopener noreferrer">genimage</a>, you must make sure to allocate the env partitions at the right flash offsets and then store the uboot env there. </p><p>The final partition config in <code>genimage.cfg</code> looks like this: </p><div class="language-conf codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-conf codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">image sdcard.img {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    hdimage {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        partition-table-type = "gpt"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition fsbl1 {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "%ATFBIN%"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition fsbl2 {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "%ATFBIN%"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition fip {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "fip.bin"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition u-boot-env {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "uboot-env.bin"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        # Matches CONFIG_ENV_OFFSET in U-Boot config</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        offset = 0x900000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        # Matches CONFIG_ENV_SIZE in U-Boot config</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        size = 0x2000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition u-boot-env-red {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "uboot-env.bin"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        # Matches CONFIG_ENV_OFFSET_REDUND in U-Boot config</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        offset = 0x940000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        # Matches CONFIG_ENV_SIZE in U-Boot config</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        size = 0x2000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition rootfs-a {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "rootfs.ext4"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        bootable = "yes"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        size = 500M</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition rootfs-b {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "rootfs.ext4"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        size = 500M</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    partition data {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        image = "data.img"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>So, when creating the image, these partitions are loaded with the environment from the
<code>uboot-env.bin</code> file. But where does this file come from you ask?! Well, it is created by the
uboot-tools package, because in <code>coremp135_defconfig</code>, we specify the right options: </p><div class="language-conf codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-conf codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Need to customize u-boot env for OTA support</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_HOST_UBOOT_TOOLS=y</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE=y</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE="$(BR2_EXTERNAL_COREMP135_PATH)/board/coremp135/uEnv.txt"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE="0x2000"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_REDUNDANT=y</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>What goes in the env? Well, again as usual there are a few ways that one can go about it. What I
ended up using was the countdown method, where u-boot keeps track of two counters: <code>BOOT_A_LEFT</code> and
<code>BOOT_B_LEFT</code>. Each time u-boot boots from one of the partitions, it decrements the counter. If the
counter for A reaches 0, it boots from B instead. When the linux image successfully boots, it sets
the counter for the partition it booted from to 3 -- this is done by running <code>rauc status mark-good</code>
in rc.local at boot. </p><p>To access the env from userspace, you use the <code>fw_printenv</code> and <code>fw_setenv</code> commands. These are
configured via <code>/etc/fw_env.config</code>, which must also be setup to match the partitions of the env
partitions, but here we can at least access them by label instead of by offset -- although, do note
that you must enable eudev in order to get the <code>/dev/disk/by-partlabel</code> symlinks created.</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">/dev/disk/by-partlabel/u-boot-env 0 0x2000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">/dev/disk/by-partlabel/u-boot-env-red 0 0x2000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>SquashFS must also be enabled for both u-boot and the kernel. RAUC on the target has to be
configured via <code>/etc/rauc/system.conf</code>, and also the RAUC bundle itself has to be built as part of
the <code>post-image.sh</code> hook defined in the BSP external tree, using a key you created (see
<code>generate_rauc_key.sh</code>) to sign it. If this is feeling all a bit convoluted...well, I agree! That's
why I'm trying to make this BSP as re-usable as I can for myself.  </p><p>If you get all that working, then OTA updates can be performed by simply running a command to grab
the image from an HTTP server somewhere: </p><p><code>rauc install https://example.com/bundle.raucb</code></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="checkout-the-repo">Checkout the repo<a href="#checkout-the-repo" class="hash-link" aria-label="Direct link to Checkout the repo" title="Direct link to Checkout the repo">​</a></h2><p>My CoreMP135 BSP is stored on github: <a href="https://github.com/mcbridejc/coremp135-bsp" target="_blank" rel="noopener noreferrer">https://github.com/mcbridejc/coremp135-bsp</a></p><p>The goal is for this to be a base layer, allowing an application repo to include it as a submodule,
and then build on top of it to add application specific stuff. But of course, you can also just fork
it and modify it.  </p><p>To build a filesystem, you can check out buildroot, and checkout coremp135-base, and then use
buildroot make, e.g.: </p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git clone -b st/2024.02.9 https://github.com/bootlin/buildroot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git clone https://github.com/mcbridejc/coremp135-bsp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cd buildroot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">make BR2_EXTERNAL=../coremp135-bsp coremp135_defconfig</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">make -j4</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>To use RAUC, you need to generate keys (see <code>coremp135-bsp/generate_rauc_keys.sh</code>) and store them
somewhere. Then you can pass their location in using the environment variables <code>RAUC_CERT_PATH</code> and
<code>RAUC_KEY_PATH</code>. You may also want to set <code>RAUC_COMPATIBLE</code> with a unique compatibility string for
your device. </p><p>I also recommend copying a public SSH key to <code>buildroot/output/target/root/.ssh/authorized_keys</code> so
you can use it to log in. You can customize the ETH1 static IP address if you like by editing
<code>coremp135-bsp/board/overlay/etc/network/interfaces</code>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps-adding-a-custom-application">Next steps: Adding a custom application<a href="#next-steps-adding-a-custom-application" class="hash-link" aria-label="Direct link to Next steps: Adding a custom application" title="Direct link to Next steps: Adding a custom application">​</a></h2><p>Next up: <a href="/blog/2025/10/27/building-a-rust-application-for-the-coremp135-using-slint">Building a Rust Application for the CoreMP135 using Slint</a></p>]]></content:encoded>
            <category>coremp135</category>
            <category>embedded</category>
            <category>linux</category>
            <category>buildroot</category>
            <category>rust</category>
        </item>
        <item>
            <title><![CDATA[Building Custom Steel and Wood Furniture]]></title>
            <link>https://jeffmcbride.net/blog/2025/09/14/steel-wood-furniture</link>
            <guid>https://jeffmcbride.net/blog/2025/09/14/steel-wood-furniture</guid>
            <pubDate>Sun, 14 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[My process for building tables]]></description>
            <content:encoded><![CDATA[<p>I recently finished building a pair of bedside tables in a stlye I've used a
couple times before. This post is about the project and the process I used to do
it. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="why">Why?<a href="#why" class="hash-link" aria-label="Direct link to Why?" title="Direct link to Why?">​</a></h2><p>It's certainly not to save money. One reason is that it's fun to have projects.
The other reason is that I can decide exactly what dimensions and features I
want, rather than shopping around and settling for something else, and I think
the steel frame ends up being a lower material cost and lower effort than using
more wood. And If I'm being completely honest, a big reason is simply this:
<strong>Melting metal with electricity is a rush</strong>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="caveats">Caveats<a href="#caveats" class="hash-link" aria-label="Direct link to Caveats" title="Direct link to Caveats">​</a></h2><p>I'm going to talk about what I did here. You should not infer from this that I
have any idea what I'm talking about, and I'm not going to try to make a
tutorial. Especially when it comes to welding, I am a complete noob. I've done
this a few times now, and it works for me, but someone who knows what they are
doing may well say I'm doing it all wrong. I learned everything I know about
welding from...well, basically two youtube videos. If you read this andthink,
"wow I can't believe he did it like that", feel free to reach out and tell me
how I should have done it better!</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-bedside-tables">The bedside tables<a href="#the-bedside-tables" class="hash-link" aria-label="Direct link to The bedside tables" title="Direct link to The bedside tables">​</a></h2><p>Let's just start with some photo of the final products, shall we? That way
everyone knows what I'm talking about. </p><p>I built two of these this summer. I like the double level table top, because it
allows for including power outlets in a more out-of-the-way location, and for
keeping books and such on the bottom, while leaving the top relatively
uncluttered for storing a phone, or grabbing a glass of water in the middle of
the night.</p><p><img loading="lazy" alt="Front View" src="/assets/images/front-4951b6419bd0868af4b3533c2d92280b.jpg" width="1600" height="1094" class="img_YgWV">
<img loading="lazy" alt="Back View" src="/assets/images/back-bb51d3ae0bfa76e34c2256b1cea70858.jpg" width="1600" height="1087" class="img_YgWV"></p><p>These are built from 3/4" square steel tubes welded together and painted black,
and from 1x2 or 1x3 pine boards glued into panels. The drawers are built from
single boards for the face, and 0.5" plywood for the sides, with 0.25" plywood
bottoms. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="getting-the-steel">Getting the steel<a href="#getting-the-steel" class="hash-link" aria-label="Direct link to Getting the steel" title="Direct link to Getting the steel">​</a></h2><p>For these, I used <a href="https://www.steelsupplylp.com/sku/108820" target="_blank" rel="noopener noreferrer">16ga red oxide square
tubes</a> from steelsupplylp.com. They
will cut it to desired lengths for you for a very reasonable price, which is
great because then I don't have to cut it, and it makes the size reasonable for
shipping. They say they cut to a 1/8" accuracy, but every time I've ordered
they've been more accurate than that (accurate enough that they seem perfect for
my purposes).</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="welding">Welding<a href="#welding" class="hash-link" aria-label="Direct link to Welding" title="Direct link to Welding">​</a></h2><p>After doing some reading, and watching some youtube videos, I decided that the
cheapest way to achieve what I wanted was to go to Harbor Freight and buy a
cheap flux-core arc welder (FCAW). Some other gear is also critical, e.g.: </p><ul><li>Big gloves to insulate and protect our hands from the flying molten metal</li><li>Thick, heavy clothes to cover your skin -- again to protect from the flying
molten metal. No really. I melted many holes in the synthetic fleece I wore
the first time. Liquid metal goes all over the place. You need protection.
Also probably a good idea not to do it around things that catch on fire
easily. </li><li>A face mask for skin and eye protection. Also because flipping your face mask
up and down as you work is part of what makes welding cool and fun. You need
one of these. </li><li>A leather apron helps cover more of your clothes -- molten metal again...</li><li>I found these magnetic right angle jigs to be super useful for holding things
in place while you tack them. </li><li>An angle grinder. You will want to grind those horrible blobby welds you made
down to something a little more smooth and presentable. "An angle grinder and
paint make me the welder I ain't", they say. </li></ul><p>The first time I did this, I did a test weld. It looked terrible, and it broke
immediately under strain. I did 10 more, and they got much better. Am I good?
No. But steel is strong, and I'm making simple tables, so mediocre will do here.
If you're about to do this for the first time, I definitely recommend having
some extra scrap tubes to practice on first. There are two adjustments on the
welder: Wire feed speed and current. I found that I had to go pretty low on the
current for these thin walled tubes, or else I ended up just blowing holes into
the steel wall rather than welding them together. </p><p>I'm not going to try to teach anyway how to weld because I suck at it and there
are better resources. All I will say is that this is, in my opinion, <strong>totally
worth trying</strong>. I cannot properly explain just how satisfying it is to melt two
pieces of metal together. </p><p><img loading="lazy" alt="Welding Gear" src="/assets/images/welding_gear-0bcb7674ff755f9ee6d5999d5fbce993.jpg" width="1452" height="1600" class="img_YgWV"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="wood">Wood<a href="#wood" class="hash-link" aria-label="Direct link to Wood" title="Direct link to Wood">​</a></h2><p>I ought some 1x3 "select pine" boards from home depot. For the second table, the
1x3's were out of stock, so I went with 1x2 boards. These I glued up into panels
for the table top, and for the five sides of the box. I built the two tables in
series, rather than parallel, and so the process on the second evolved somewhat.
Mainly, I finished the wood panels and installed drawer slides before gluing
them into the box, and I built the box first and used it as a jig for doing the
steel tube assembly. </p><p>Drawers are made from some 0.5" ply, 0.25" ply (bottom) and 1x8 board (face) I
had lying around as scrap.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="painting">Painting<a href="#painting" class="hash-link" aria-label="Direct link to Painting" title="Direct link to Painting">​</a></h2><p>After welding, and grinding the joints down flat with the angle grinder, I paint
the metal with Rust-oleum flat black spray paint. Two coats, plus maybe a bit of
touch up if I missed any spots. </p><p>For the wood, I used Minwax Polyshades, with a satin finish. It seems to be
pretty good. I've tried a couple others in the past, and these is easy to apply
(rather than stain + poly later) and it holds up well to water and abuse. I do
really struggle with getting an even coat, and avoiding drips. I suspect this is
just bad technique though. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="bom-and-material-cost">BOM and Material Cost<a href="#bom-and-material-cost" class="hash-link" aria-label="Direct link to BOM and Material Cost" title="Direct link to BOM and Material Cost">​</a></h2><table><thead><tr><th>Descrpition</th><th>Source</th><th>Price (per table)</th></tr></thead><tbody><tr><td>288" 0.75" 16ga tube</td><td><a href="https://www.steelsupplylp.com/sku/108820" target="_blank" rel="noopener noreferrer">Steel Supply LP</a></td><td>$29 (shipped)</td></tr><tr><td>Select pine boards</td><td><a href="https://www.homedepot.com/p/1-in-x-3-in-x-8-ft-Select-Pine-Board-922022/202535803" target="_blank" rel="noopener noreferrer">Home Depot</a></td><td>~$96</td></tr><tr><td>Drawer Slides</td><td><a href="https://www.amazon.com/dp/B08L7M6VZX" target="_blank" rel="noopener noreferrer">Amazon</a></td><td>$13</td></tr><tr><td>Handles</td><td><a href="https://www.amazon.com/dp/B07FDRTZY8" target="_blank" rel="noopener noreferrer">Amazon</a></td><td>$7</td></tr><tr><td>Recessed Power Strip</td><td><a href="https://www.amazon.com/dp/B0BN54HBTT" target="_blank" rel="noopener noreferrer">Amazon</a></td><td>$34</td></tr><tr><td>Plastic feet</td><td><a href="https://www.amazon.com/dp/B06XFLDXP3?th=1" target="_blank" rel="noopener noreferrer">Amazon</a></td><td>$5</td></tr><tr><td></td><td></td><td></td></tr><tr><td></td><td><strong>Total</strong>:</td><td>$184</td></tr></tbody></table><p>Not including a bit of 1x8 board and plywood that I used scrap for. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-tables">Other Tables<a href="#other-tables" class="hash-link" aria-label="Direct link to Other Tables" title="Direct link to Other Tables">​</a></h2><p>This is actually the third project since I bought the welder. First I built these...</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="couch-end-table">Couch End Table<a href="#couch-end-table" class="hash-link" aria-label="Direct link to Couch End Table" title="Direct link to Couch End Table">​</a></h3><p>We have a convertible couch in our guest room, and I wanted a narrow table to go
between it and the wall. It's main use is as a place to sit and read, or if we
have guests, a pull out bed. So, it needed a place to put a drink, a lamp, and
to charge devices. I really wanted the lenght of it to match the couch. </p><p><img loading="lazy" alt="Couch and Table" src="/assets/images/couch_table-9e6b4873a571d67e84fa5ee97abfbd94.jpg" width="2694" height="2238" class="img_YgWV">
<img loading="lazy" alt="Table alone" src="/assets/images/couch_table2-0cb84701fb1c7557968b2adc1b41c349.jpg" width="1600" height="1063" class="img_YgWV"></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="end-of-hall-table">End of hall table<a href="#end-of-hall-table" class="hash-link" aria-label="Direct link to End of hall table" title="Direct link to End of hall table">​</a></h3><p>This one is just a bit of extra storage, and to decorate the blank end of our
hallway. I found a peice of this wormwood board at a reclaimed furniture store
and used that for the table top. Very simple construction with just a steel
frame, and a couple of boards screwed onto that. The worst part of this one was
getting stain into all those holes with a q-tip -- that was a tedious job!</p><p><img loading="lazy" alt="Hall Table" src="/assets/images/hall_table1-7cb3443d390e47df40247c08b3eb71ed.jpg" width="2187" height="2656" class="img_YgWV"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="some-more-process-photos">Some more process photos<a href="#some-more-process-photos" class="hash-link" aria-label="Direct link to Some more process photos" title="Direct link to Some more process photos">​</a></h2><p>To wrap up, here's a random assortment of build photos...</p><p><img loading="lazy" alt="Process 1" src="/assets/images/process1-30eb80b959df57c196f081be2938bd32.jpg" width="1600" height="1592" class="img_YgWV">
<img loading="lazy" alt="Process 2" src="/assets/images/process2-795d114f210b8b34323a7d745306165d.jpg" width="1600" height="900" class="img_YgWV">
<img loading="lazy" alt="Process 3" src="/assets/images/process3-996b6489b08f881ac1d2465f9f7c2821.jpg" width="1341" height="1600" class="img_YgWV">
<img loading="lazy" alt="Process 4" src="/assets/images/process4-cda28084de44a4958b116291b2b68ace.jpg" width="1572" height="1600" class="img_YgWV">
<img loading="lazy" alt="Process 5" src="/assets/images/process5-3731a0d31362fa478ad285da96ec9838.jpg" width="1600" height="1047" class="img_YgWV">
<img loading="lazy" alt="Process 6" src="/assets/images/process6-ab0cc58cc7c10ddab6f9d4a9bf2ecbf5.jpg" width="1600" height="1200" class="img_YgWV"></p>]]></content:encoded>
            <category>furniture</category>
            <category>projects</category>
        </item>
        <item>
            <title><![CDATA[Zencan Device Demo Video]]></title>
            <link>https://jeffmcbride.net/blog/2025/06/18/zencan-device-demo</link>
            <guid>https://jeffmcbride.net/blog/2025/06/18/zencan-device-demo</guid>
            <pubDate>Wed, 18 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[A quick live demo of zencan as it stands]]></description>
            <content:encoded><![CDATA[<p>Two weeks ago, I posted about a <a href="/blog/2025/06/05/introducing-zencan">Rust CANOpen Stack</a> I was
working on. It was in a bit of a disfunctional state at the time. Since then, I've ported two
firmware projects to use it and in the process made a lot of progress on it! There's still a ton to
do to get it where I want, but today I recorded a quick live demo of the first two boards
communicating using zencan! Production quality is low, but hopefully it's still a useful way to get
a feel for what it is trying to do.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="video">Video<a href="#video" class="hash-link" aria-label="Direct link to Video" title="Direct link to Video">​</a></h2><iframe title="Zencan Demo/Walkthrough" width="560" height="315" src="https://video.jeffmcbride.net/videos/embed/4gbFyrZSE9ZaDYqivw3mpB" frameborder="0" allowfullscreen="" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe><h2 class="anchor anchorWithStickyNavbar_LWe7" id="notes">Notes<a href="#notes" class="hash-link" aria-label="Direct link to Notes" title="Direct link to Notes">​</a></h2><p>Code running on the boards:</p><ul><li>can-io: <a href="https://github.com/mcbridejc/can-io-firmware" target="_blank" rel="noopener noreferrer">https://github.com/mcbridejc/can-io-firmware</a></li><li>i4-controller: <a href="https://github.com/mcbridejc/i4-controller-firmware" target="_blank" rel="noopener noreferrer">https://github.com/mcbridejc/i4-controller-firmware</a></li></ul>]]></content:encoded>
            <category>rust</category>
            <category>programming</category>
            <category>embedded</category>
            <category>zencan</category>
        </item>
        <item>
            <title><![CDATA[Introducing Zencan: Easy CANOpen with Rust]]></title>
            <link>https://jeffmcbride.net/blog/2025/06/05/introducing-zencan</link>
            <guid>https://jeffmcbride.net/blog/2025/06/05/introducing-zencan</guid>
            <pubDate>Thu, 05 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Releasing a new project for developing CAN bus devices with embedded rust]]></description>
            <content:encoded><![CDATA[<p>I've been kicking around an idea for a while now to create a CAN bus communication stack for Rust,
and now it is finally taking shape. It's still a work-in-progress, but I'm getting ready to publish
a rough prototype, so I want to write about what I want it to be. I'm calling it <em>Zencan</em>, and it's an
implementation of the <a href="https://www.csselectronics.com/pages/canopen-tutorial-simple-intro" target="_blank" rel="noopener noreferrer">CANOpen</a>
protocol, with a few planned extensions.</p><p>The repo for zencan is at <a href="https://github.com/mcbridejc/zencan" target="_blank" rel="noopener noreferrer">https://github.com/mcbridejc/zencan</a>.</p><p>An example project using zencan can be found at <a href="https://github.com/mcbridejc/can-io-firmware" target="_blank" rel="noopener noreferrer">https://github.com/mcbridejc/can-io-firmware</a></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="background">Background<a href="#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="whats-a-can-bus">What's a CAN bus?<a href="#whats-a-can-bus" class="hash-link" aria-label="Direct link to What's a CAN bus?" title="Direct link to What's a CAN bus?">​</a></h3><p>The Controller Area Network (CAN) bus, first popularized in automotive applications, is widely used
for industrial automation and motion control. If you've ever used an OBD-II reader to read engine
error codes, you were using a CAN bus. I've personally used it in UAVs and on rocket engine
controllers, but I feel that it does not get as much use in the open-source world as it deserves, so
I want to make CAN easy with Rust in hopes that it will encourage more use.</p><p>The CAN bus operates on a single differential pair, connected to all of the nodes. This means wiring
multiple devices requires only two wires! It also means a single connection point can be used to
plug in a computer and monitor and control all of the MCUs on the bus. It keeps wiring easy.</p><p>Many MCUs come with CAN controllers, and they handle a lot of the communications overhead without
any CPU involvement. For example, bus arbitration, errors and re-transmission, prioritized message
queuing, and received message filtering are all often supported by hardware.</p><p>CAN is fairly slow, with traditional CAN 2.0 busses running at a max bitrate of 1 Mbit/s. However,
these days some MCUs are shipping with CAN-FD capable controllers, and I intend for Zencan to
support CAN-FD. A CAN-FD bus allows for longer messages, and higher bitrates -- usually up to 5-8
Mbit/s, although I have heard of buses as fast as 20 Mbit/s.</p><p>The CAN protocol includes <strong>framing</strong>, so everything is sent as a <strong>message</strong>. A message has an ID,
and a data payload. The ID is used to identify what's in the message, and also implicitly, who it's
for (e.g. here is where message filtering comes in: if a node on the bus knows which messages it is
interested in, it can setup hardware filters to drop any others). I think this can be confusing
sometimes, so I will restate: generally, nodes on a CAN bus do not have addresses, or IDs as a node.
Instead, the <strong>messages</strong> are tagged with IDs. If one wants to assign addresses to specific nodes,
this has to be built on top of the CAN protocol!</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-i-like-can">Why I like CAN<a href="#why-i-like-can" class="hash-link" aria-label="Direct link to Why I like CAN" title="Direct link to Why I like CAN">​</a></h3><ul><li>It is smaller and cheaper than Ethernet.</li><li>On projects which have multiple MCUs, it is convenient to plug into a single bus and talk to all of them.</li><li>There are standard tools for monitoring and plotting data on a CAN bus, with tools like
<a href="https://www.savvycan.com/" target="_blank" rel="noopener noreferrer">SavvyCAN</a>  and the
<a href="https://www.csselectronics.com/pages/can-dbc-file-database-intro" target="_blank" rel="noopener noreferrer">DBC</a> file format one can easily
plot data with no code.</li><li>It is robust! With its low speed, smart controller hardware, and differential signalling, in my
experience CAN is very tolerant of less-than-ideal wiring scenarios.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="zencan-goals">Zencan Goals<a href="#zencan-goals" class="hash-link" aria-label="Direct link to Zencan Goals" title="Direct link to Zencan Goals">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="rust">Rust<a href="#rust" class="hash-link" aria-label="Direct link to Rust" title="Direct link to Rust">​</a></h3><p>Zencan is built in Rust because that's what I'm into lately, and there's a lack of CANOpen stacks out there for Rust.</p><p>I've been writing C/C++ for embedded systems a long time, and although there are definitely some
trade-offs, I see Rust as the path forward for me. Look, if you catch me at the wrong time -- like
when I've just spent an hour appeasing the borrow checker, or am frustrated by difficulty viewing
static variables in a debugger -- I might offer a different opinion. But on the whole...</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="configurability">Configurability<a href="#configurability" class="hash-link" aria-label="Direct link to Configurability" title="Direct link to Configurability">​</a></h3><p>I want configurability! I want to be able to build a set of components, put them all on a CAN bus,
and make them talk to each other, without having to change their firmware to do it. One way that a
CAN bus has traditionally been designed is to keep a "master spreadsheet" of all the data that has
to be transferred on the bus (motor temperature, motor current, velocity command, etc), cram these
all into a set of messages, assign them each a CAN ID, and then write the appropriate software for
each node to send and receive the relevant messages. This is fine, but I want to grab a generic
motor controller board, and a generic IO board with an analog joystick plugged into it, and then
configure the joystick to command the motor controller without modifying the software.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="observability">Observability<a href="#observability" class="hash-link" aria-label="Direct link to Observability" title="Direct link to Observability">​</a></h3><p>I want to standardize interactions one might want to have with MCUs on a bus so that I can solve
them well once and re-use it. I want to plug into the bus and:</p><ul><li>Report all the devices on the bus</li><li>Program any device with new firmware</li><li>Trivially plot values being generated by that device over time, or log for plotting later</li><li>View metadata about the device such as software versions, serial numbers, etc</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="ease">Ease<a href="#ease" class="hash-link" aria-label="Direct link to Ease" title="Direct link to Ease">​</a></h3><p>A lot of code is required to get all of that, but I shouldn't have to think about it every time I
start a new project. I should just be able to instantiate a node that works with a basic
configuration file and a small amount of boilerplate.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="architecture">Architecture<a href="#architecture" class="hash-link" aria-label="Direct link to Architecture" title="Direct link to Architecture">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="canopen">CANOpen<a href="#canopen" class="hash-link" aria-label="Direct link to CANOpen" title="Direct link to CANOpen">​</a></h3><p>There is an existing protocol, built on top of CAN, which supports a LOT of what I want to do. It's
called <a href="https://en.wikipedia.org/wiki/CANopen" target="_blank" rel="noopener noreferrer">CANOpen</a>. I think that Zencan is going to actually be
a Rust implementation of a CANOpen stack, with some extra features layered onto it. I have some
concerns about this, like the fact that CANOpen is managed by the <a href="https://www.can-cia.org/" target="_blank" rel="noopener noreferrer">CiA</a>,
which restricts access to the specification documents to members only. And even if you manage to
find these documents, you may not find them as helpful or clear as you would like. But, the concept
of the Object Dictionary and the Electronic Data Sheet (EDS) describing the objects in it, combined
with the ability to map arbitrary object data into PDO messages, solves a lot of the configurability
and observability requirements. CANOpen isn't exactly what I would design from scratch, but it is
pretty close and has the benefit of being an established standard with existing devices and software
tools. And, as far as I can find, there isn't yet a full-featured, mature CANOpen stack available
for Rust. So I'm going to start here, and see if I can get everything I want out of it while
maintaining CANOpen compatibility.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="specific-goals">Specific Goals<a href="#specific-goals" class="hash-link" aria-label="Direct link to Specific Goals" title="Direct link to Specific Goals">​</a></h3><p>Specific goals of the project are:</p><ul><li>Support creating nodes on embedded (<code>no_std</code>) or linux targets</li><li>No heap; all data statically allocated.</li><li>Be CANOpen compatible</li><li>Support device discovery</li><li>Easy node configuration and object definition via a "device config" TOML file</li><li>Support CAN-FD</li><li>Support bulk data transfer  -- e.g. a device I am targeting is an e-ink display, which requires
transferring frames of pixels</li><li>Standardized device software updates and version reporting</li><li>A GUI and CLI interface for device management via socketcan</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="configuration-files">Configuration Files<a href="#configuration-files" class="hash-link" aria-label="Direct link to Configuration Files" title="Direct link to Configuration Files">​</a></h3><p>I am still hashing this out, and it may change!</p><p>There is a file format called EDS, or Electronic Data Sheet, which is used to describe the objects
in a CANOpen object dictionary. I initially started out using an EDS file as an input to the code
generation, but found that this was not ideal. For one thing, the format is fairly
denormalized/redundant, which means that it can have inconsistencies and be difficult to edit
manually. For another, I want the ability to specify Zencan specific options, and had no (good) way
to work that into an EDS file. So instead, I've created a TOML schema for device configuration
files, and EDS files will be generated as an output to be used with tools which support them.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="static-data-shared-between-objects-and-threads-without-heap">Static Data, shared between objects and threads, without heap<a href="#static-data-shared-between-objects-and-threads-without-heap" class="hash-link" aria-label="Direct link to Static Data, shared between objects and threads, without heap" title="Direct link to Static Data, shared between objects and threads, without heap">​</a></h3><p>The first challenge was sharing data between different contexts. Maybe it's just code that doesn't
know each other (e.g. the <code>zencan-node</code> crate, and user's application code) sharing access to the
object dictionary. Maybe it is really on other threads. In a situation with <code>alloc</code> available, one
might simply use an <code>Arc</code> to wrap the shared objects. Without Arc, we have to pass references. This
quickly can lead to lifetime hell. Instead of managing these lifetimes with lots of generics, I
decided to require many of the data structures to be static. In the embedded context, this is almost
always the desired case anyway, and only one instance of a node is expected to exist. In other
contexts, like hosting a node on linux, or in tests, this may not be the case. These can be
addressed using <code>Box::leak</code>, to make a heap allocated object static.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="dynamic-code-generation">Dynamic Code Generation<a href="#dynamic-code-generation" class="hash-link" aria-label="Direct link to Dynamic Code Generation" title="Direct link to Dynamic Code Generation">​</a></h3><p>Some code will be generated in build.rs, using the <code>zencan-build</code> crate, based on a TOML file in the
project. This is somewhat similar to the way that the <a href="https://canopennode.github.io/" target="_blank" rel="noopener noreferrer">CANOpenNode</a>
C stack  does it, but the EDS file, and more specifically the <a href="https://github.com/CANopenNode/CANopenEditor" target="_blank" rel="noopener noreferrer">C#
application</a> used to edit the EDS file generate a C
source and header file for inclusion in your application. I think that rust tooling will provide a
good mechanism to auto-generate this code as part of the build process. It is still auto-generated
code, and that has its downsides -- especially readability -- but I don't see how to get around it.
The generated code is saved to the compilation OUT_DIR, its name stored in an env var, so that it
can be included via a macro somewhere in the application. This concept is modeled after
<a href="https://docs.slint.dev/latest/docs/rust/slint/docs/mcu/" target="_blank" rel="noopener noreferrer">slint</a>, which does a similar thing for
including generated code from a <code>.slint</code> file which defines the GUI.</p><p>In build.rs, the code is generated from the device config, with a name (e.g. 'EXAMPLE1'):</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token class-name">Err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">zencan_build</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">build_node_from_device_config</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"EXAMPLE1"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"device_configs/example1.toml"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">eprintln!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Error building node from example1.toml: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">process</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">exit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Then in your application, the generated code can be included wherever you like as:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token macro property" style="color:#36acaa">include_modules!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">EXAMPLE1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The name allows multiple nodes to be instantiated in a single application, although I do not yet
have a use in mind for this, other than tests.</p><p>Here's an example of what the generated code looks like, which might help understand what's being
generated:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token attribute attr-name" style="color:#00a4db">#[allow(dead_code)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[derive(Debug)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Object1000</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicCell</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[allow(dead_code)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">Object1000</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">set_value</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">store</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">get_value</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">load</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">Self</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Object1000</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicCell</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0i64</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">ObjectRawAccess</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token class-name">Object1000</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sub</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> offset</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AbortCode</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> sub </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> offset </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">sdo</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">AbortCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">UnsupportedAccess</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from_le_bytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">try_into</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map_err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">_</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">size_of</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">sdo</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">AbortCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">DataTypeMismatchLengthLow</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">sdo</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">AbortCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">DataTypeMismatchLengthHigh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_value</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AbortCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">NoSuchSubIndex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sub</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> offset</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AbortCode</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> sub </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> bytes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get_value</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to_le_bytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> offset </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">sdo</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">AbortCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">DataTypeMismatchLengthHigh</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            buf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">copy_from_slice</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">bytes</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">offset</span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">offset </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AbortCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">NoSuchSubIndex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">sub_info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sub</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">SubInfo</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AbortCode</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> sub </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AbortCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">NoSuchSubIndex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SubInfo</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            access_type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">objects</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">AccessType</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Const</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            data_type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">objects</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">DataType</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">UInt32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            size</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4usize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            pdo_mapping</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">objects</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">PdoMapping</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            persist</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">object_code</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">objects</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">ObjectCode</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">zencan_node</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">common</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">objects</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">ObjectCode</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Var</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">OBJECT1000</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Object1000</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Object1000</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">NODE_STATE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">NodeState</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token number" style="color:#36acaa">4usize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4usize</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NodeState</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">NODE_MBOX</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">NodeMbox</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NodeMbox</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">NODE_STATE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpdos</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">OD_TABLE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">ODEntry</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">31usize</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ODEntry</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        index</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0x1000</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ObjectData</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Storage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token constant" style="color:#36acaa">OBJECT1000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Each object gets a struct defined, and an implementation of the <code>ObjectRawAccess</code> trait. All objects
are instantiated statically, and stored as a table in <code>OD_TABLE</code>. This is the object dictionary.
<code>NODE_STATE</code> includes some static state information used by the instantiated Node, and <code>NODE_MBOX</code>
provides a Sync data structure for pass received messages, so that messages can be received in an
IRQ handler.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="threading">Threading<a href="#threading" class="hash-link" aria-label="Direct link to Threading" title="Direct link to Threading">​</a></h3><p>The expectation is that a single thread will own the <code>Node</code> object, and that most of the node
behavior will happen on this thread in the form of calls to <code>Node::process</code>. A separate object, the
<code>NodeMbox</code> allows for reception of messages on another thread. The expected use for this is to push
received messages into the mailbox object in an IRQ handler. The object dictionary is Sync, using
the <a href="https://docs.rs/critical-section/latest/critical_section/" target="_blank" rel="noopener noreferrer">critical_section</a> crate for
protecting data access. Critical section will allow embedded applications to implement critical
sections by disabling interrupts, and linux applications to do so using global locks.</p><p>I tried to use <a href="https://docs.rs/crossbeam/latest/crossbeam/" target="_blank" rel="noopener noreferrer">crossbeam</a>'s
<a href="https://docs.rs/crossbeam/latest/crossbeam/atomic/struct.AtomicCell.html" target="_blank" rel="noopener noreferrer">AtomicCell</a> for atomic
access, but it does not currently support thumbv6 (i.e. Cortex M0) targets at all, because these
targets lack CAS support, and I intend to use this on M0 targets.</p><p>The object dictionary, and all of the objects are Sync, as they may need to be accessed by various
application code running in various thread contexts.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="object-storage-vs-callback">Object Storage vs Callback<a href="#object-storage-vs-callback" class="hash-link" aria-label="Direct link to Object Storage vs Callback" title="Direct link to Object Storage vs Callback">​</a></h3><p>Zencan supports two object types:</p><ul><li><em>Storage</em> objects have statically allocated storage for their data and support simple read/write
operations</li><li><em>Callback</em> objects rely on callback functions to implement their access, allowing for validation
and dynamic data handling during read or write</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="control-tools">Control tools<a href="#control-tools" class="hash-link" aria-label="Direct link to Control tools" title="Direct link to Control tools">​</a></h3><p>The <code>zencan-cli</code> crate comes with a REPL-style shell for interacting with devices over socketcan in
real-time. A GUI version of this is planned as well.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary">​</a></h2><p>I consider Zencan now as a prototype, and still evolving. It needs more examples, documentation, and
I need to implement it in more devices to flesh things out. There are still important features
missing, and I expect some churn on the architecture/API. I hope over the next few months to
integrate it into a few more projects, while continuing to develop it into something that someone
besides myself might want to use! There are a few loose ends to tie up before I push a first release
to crates.io, but I expect to be doing that soon.</p>]]></content:encoded>
            <category>rust</category>
            <category>programming</category>
            <category>embedded</category>
            <category>zencan</category>
        </item>
        <item>
            <title><![CDATA[Errors using RTT and WFI ]]></title>
            <link>https://jeffmcbride.net/blog/2025/05/22/rtt-errors-with-wfi</link>
            <guid>https://jeffmcbride.net/blog/2025/05/22/rtt-errors-with-wfi</guid>
            <pubDate>Thu, 22 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Errors using probe-rs and RTT in conjuction with WFI on STM32G0]]></description>
            <content:encoded><![CDATA[<p><em>This is for future-me, and for future internet searchers.</em></p><p>Using probe-rs to attach to an STM32G0 family MCU to read log messages via defmt over RTT, I encountered the following error:</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"> WARN probe_rs::util::rtt::client: RTT read pointer changed, re-attaching</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> WARN probe_rs::rtt::channel: RTT channel name points to unrecognized memory. Bad target description?</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> WARN probe_rs::rtt::channel: RTT channel name points to unrecognized memory. Bad target description?</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This occurred the same using <a href="https://docs.rs/defmt-rtt/latest/defmt_rtt/" target="_blank" rel="noopener noreferrer">defmt_rtt</a> or
<a href="https://docs.rs/rtt-target/latest/rtt_target/" target="_blank" rel="noopener noreferrer">rtt_target</a>.</p><p>Reading through the probe-rs logs, it seemed that at some point after correctly reading the RTT
memory block, it would start reading junk where it expected to read a <code>SEGGER RTT</code> identifier.</p><p>I am using <a href="https://docs.rs/lilos/latest/lilos/" target="_blank" rel="noopener noreferrer">lilos</a>, and in its executor it uses the WFI
instruction to sleep. By trying different configurations, I found that the error only occurs when
the lilos executor is run.</p><p>On many cortex processors, some options have to be enabled to keep the clocks running on the debug
core during sleep, e.g., on the STM32G0, the following bits have to be set:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token namespace" style="opacity:0.7">pac</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">DBGMCU</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cr</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">modify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">w</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_dbg_standby</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_dbg_stop</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>What I learned today is that while this may keep the dbg core running, either the SRAM or something
in the bus matrix still gets disabled unless there is at least one active master, and I guess the
debug core does not count. So to keep access to SRAM via the debugger during sleep, you can enable a
DMA:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token namespace" style="opacity:0.7">pac</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">RCC</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ahbenr</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">modify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">w</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_dma1en</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>With all three of these bits set, I can reliably read from SRAM over SWD and thus RTT is happy.</p><p><a href="https://github.com/probe-rs/probe-rs/issues/350#issuecomment-740550519" target="_blank" rel="noopener noreferrer">This probe-rs issue</a>
discusses the problem.</p>]]></content:encoded>
            <category>rust</category>
            <category>programming</category>
            <category>embedded</category>
        </item>
        <item>
            <title><![CDATA[Using a Rust async function as a polled state machine]]></title>
            <link>https://jeffmcbride.net/blog/2025/05/16/rust-async-functions-as-state-machines</link>
            <guid>https://jeffmcbride.net/blog/2025/05/16/rust-async-functions-as-state-machines</guid>
            <pubDate>Fri, 16 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[How to manually poll an async function and use the rust compiler as a state machine generator]]></description>
            <content:encoded><![CDATA[<p><em>How to poll an async function manually, and then use the rust compiler as a finite-state-machine generator</em></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2><p>An interesting thing about Rust async functions is that what that <code>async</code> keyword actually does is
tell the compiler to automatically convert your function into a state machine so that it can pick up
where it left off, and have it return a
<a href="https://doc.rust-lang.org/core/task/enum.Poll.html" target="_blank" rel="noopener noreferrer">core::task::Poll</a> result every time it's poll
method is called. The future object get packed with any data it needs to keep track of it's
execution state.</p><p>Normally, a one doesn't call this poll method directly, but uses an Executor like
<a href="https://docs.rs/tokio/latest/tokio/" target="_blank" rel="noopener noreferrer">tokio</a> or <a href="https://docs.rs/lilos/latest/lilos/" target="_blank" rel="noopener noreferrer">lilos</a> to poll
it. The executor may not necessarily poll it in a busy loop, it may end up blocking the OS task
waiting for file handles to be ready, or waiting for an interrupt to go off to flag the task as
ready to run. But, there's nothing stopping you from calling poll yourself!</p><p>I've done this a few times, in a couple basic scenarios, and I think it can be useful. At least,
it's useful to know how to do it. The basic premise is that sometimes, you need to build a state
machine that gets called periodically, and steps through a process. For complicated state machines,
this can be keeping track of a lot of state transitions with big match variables. It's fine, but
sometimes I find that the state machine written as such is hard to reason about, compared to
performing the same sequence of events in a blocking manner.</p><p>The full demo code from this article can be found <a href="https://github.com/mcbridejc/rust-async-state-machines-demo" target="_blank" rel="noopener noreferrer">on github</a></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="linear-sequence-vs-state-machine">Linear sequence vs state machine<a href="#linear-sequence-vs-state-machine" class="hash-link" aria-label="Direct link to Linear sequence vs state machine" title="Direct link to Linear sequence vs state machine">​</a></h2><p>As a simple comparison, consider a sequence of register initializations:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/// A somewhat psuedo-codey demonstration of sending a series of commands</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// to a device and waiting for an acknowledgement</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">init_device</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> device </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ImaginaryDeviceCommander</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">command</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"write REG1 10"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">is_ready</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">command</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"write REG2 20"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">is_ready</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">command</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"write REG3 30"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">is_ready</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>But now imagine that our process can't block. Maybe it is part of a "super loop": an application
with a single thread that cyclically calls many modules so they can update themselves. Now the
device initialization process needs to be refactors so that it can be performed iteratively over a
series of function calls which always return quickly, something like this:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">DeviceInitter</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    command_sent</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    step</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    device</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ImaginaryDeviceCommander</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">DeviceInitter</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> step </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> command_sent </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">is_ready</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">step </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">command_sent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token boolean" style="color:#36acaa">false</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">step </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">command</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"write REG1 10"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">command</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"write REG2 20"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">device</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">command</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"write REG3 30"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">command_sent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">step </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Complete!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The first version certainly seems nicer to read and understand!</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-manually-poll-an-async-function">How to manually poll an async function<a href="#how-to-manually-poll-an-async-function" class="hash-link" aria-label="Direct link to How to manually poll an async function" title="Direct link to How to manually poll an async function">​</a></h2><p>There are two main things to know:</p><ol><li>You have to pin it</li><li>You have to create a dummy context to pass to poll</li></ol><p>Both are easy to do!</p><p>Finally, you need to make sure your future will yield at appropriate times. Normally, async
functions yield back to the executor when they stop to wait on some IO operation to the OS, such as
reading a network socket. But you can also use the
<a href="https://docs.rs/futures/latest/futures/macro.pending.html" target="_blank" rel="noopener noreferrer">pending!()</a> macro to yield at any point.</p><p>Here is a function to run a future once, and a simple state machine demoing it's use:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">core</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">pin</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Pin</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// Poll a future one time, and return its result if it completes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">poll_once</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Pin</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">dyn</span><span class="token plain"> </span><span class="token class-name">Future</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Output</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> cx </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">futures</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">task</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Context</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from_waker</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">futures</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">task</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">noop_waker_ref</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">as_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">poll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> cx</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">core</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">task</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Poll</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Ready</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token class-name">Some</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">core</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">task</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Poll</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Pending</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> future </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">pin!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">loop</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">42</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                i </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// Yield back to the executor. This means that</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// the future's `poll` function will return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// `Poll::Pending` and the subsequent call will</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// pick up here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token macro property" style="color:#36acaa">pending!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// i = 0. Not done.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">assert_eq!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">poll_once</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">future</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">as_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// i = 1. Not done.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">assert_eq!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">poll_once</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">future</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">as_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// i = 2. Done!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">assert_eq!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">poll_once</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">future</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">as_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Some</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">42</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>There's no async runtime like tokio, async-io, etc, here; the only dependency is the
<a href="https://docs.rs/futures/latest/futures/" target="_blank" rel="noopener noreferrer">futures</a> crate.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="use-case-chunked-serialization">Use case: chunked serialization<a href="#use-case-chunked-serialization" class="hash-link" aria-label="Direct link to Use case: chunked serialization" title="Direct link to Use case: chunked serialization">​</a></h2><p>One reason I wrote this article is that a library I am working on needed to serialize a handful of
data structures in an embedded context to persist it to flash. I want to impose minimum requirements
on the application, so:</p><ul><li>No heap usage, which means no returning a <code>Vec&lt;u8&gt;</code>.</li><li>Do not assume the serialized output will fit in RAM. It has to be able to be written to flash
in small chunks. Only the application knows what "small" means here.</li></ul><p>This means that the serializer has to expect a series of <code>read(buf: &amp;mut [u8])</code> calls, copy the next
N bytes into the buffer, and then keep track of where it was so that it can pick up where it left
off on the next call to <code>read</code>. This is kind of a pain in the ass! It means, e.g., that when
serializing a u32, it may end up writing the first byte on one call to read, and the next 3 bytes on
the next.</p><p>I started writing a state machine to do this, and then decided to try it as an async function. As an
example for this article, I simplified the serialization a bit, but it is essentially the same. We
are going to serialize some objects that look like this:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/// Just an example of an object to be serialized.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// Each object has a type, and a block of bytes to describe it.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Object</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> object_type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Vec</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u8</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>They will get serialized into the flash as <code>[&lt;length:u16&gt; &lt;object_type:u8&gt; &lt;data:n&gt;]</code>, where length
is the length of the data + object type byte.</p><p>So first, I need to create an async function that serializes the data, <strong>but yields after writing
out each byte</strong>:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/// Utility to write bytes to a provided function, returning a Poll::Pending between each byte</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">write_bytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">src</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> write_fn</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">FnMut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">src</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">write_fn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">src</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">pending!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// Implements a serializer for a list of objects.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// Implementing this as an async function allows the sequence of writes to be written linearly and</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// simply, allowing rustc to compile it into a state machine so that the serialization can be</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// broken up into arbitrary chunks</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">polling_write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">objects</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">Object</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> write_fn</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">FnMut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> obj </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> objects </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// First serialize the size of the object, which is the length of the data + 1 byte for the</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// object type</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> len </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">obj</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u16</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">write_bytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">len</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to_le_bytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> write_fn</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// Serialize the object type</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">write_bytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">obj</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">object_type</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> write_fn</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// Serialize the object data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">write_bytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">obj</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> write_fn</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Great, that wasn't so bad.</p><p>Now, lets wrap up the future into a struct that can provide the required read function:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">AsyncSerializer</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token lifetime-annotation symbol" style="color:#36acaa">'b</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">F</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Future</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Output</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    fut</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Pin</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'a</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">F</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    reg</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'b</span><span class="token plain"> </span><span class="token class-name">RefCell</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u8</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token lifetime-annotation symbol" style="color:#36acaa">'b</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">F</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">AsyncSerializer</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token lifetime-annotation symbol" style="color:#36acaa">'b</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">F</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">where</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">F</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Future</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Output</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Create a serializer using a future and a shared data buffer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// The future should write to reg, and it *must yield after writing each byte*.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">fut</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Pin</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'a</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">F</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> reg</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'b</span><span class="token plain"> </span><span class="token class-name">RefCell</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u8</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">Self</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">Self</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> fut</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> reg </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> pos </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">loop</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> pos </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> pos</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token class-name">Some</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">_</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">poll_once</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fut</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">as_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// Serialization is complete</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> pos</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                buf</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">pos</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">reg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">borrow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                pos </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>And finally, put it together and use it:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// `byte_buf` serves as a temporary register for communication between the future which implements</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// serialization and the AsyncSerializer wrapper</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> byte_buf </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RefCell</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0u8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Create the future from an async function, each time it is polled, it will write one byte to</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// `byte_buf`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> future </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">pin!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">polling_write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">objects</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">b</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">byte_buf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">borrow_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// instantiate the wrapper which will drive the future</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> async_serializer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AsyncSerializer</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">future</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">byte_buf</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// A vec to store the fully written data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> output </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Vec</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// A temporary small buffer. Data will be serialized one 3-byte chunk at a time into this buffer.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> buf </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">loop</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> write_size </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> async_serializer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        output</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">extend_from_slice</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">buf</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">write_size</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> write_size </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">assert_eq!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">output</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">9</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">7</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">8</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This is made a little more complicated by the requirement that it not use the Heap. If we could use
the heap, the future could be wrapped by <code>Box::pin</code>, and that makes managing lifetimes easier. As it
is, we need to pin the future on the stack, which means that the stack frame it is created on has to
outlive the serialization process. To make this a easier on the user, we can create a function to
create the future and the shared RefCell, wrap them up, and provide them to a user provided callback:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Create a serializer for objects, and pass it to the provided callback</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// This allows for pinning the required data on the stack for the duration of the serializer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// lifetime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">serialize_objects</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">objects</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">Object</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> cb</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">FnMut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">dyn</span><span class="token plain"> </span><span class="token class-name">PersistSerializer</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> reg </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RefCell</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0u8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> fut </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">pin!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">polling_serializer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">objects</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">b</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">reg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">borrow_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> serializer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AsyncSerializer</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">fut</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">reg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">cb</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> serializer</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>And then the usage becomes:</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// A vec to store the fully written data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> async_output </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Vec</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">async_serialize</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">serialize_objects</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">objects</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">serializer</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// A temporary small buffer. Data will be serialized one 3-byte chunk at a time into this buffer.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> buf </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">loop</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> write_size </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> serializer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            async_output</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">extend_from_slice</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">buf</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">write_size</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> write_size </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="trade-offs">Trade-offs<a href="#trade-offs" class="hash-link" aria-label="Direct link to Trade-offs" title="Direct link to Trade-offs">​</a></h2><p>To be honest, I'm not 100% convinced this is a great idea. There are <em>for sure</em> times when it's
better to write out a sequence of linear actions. But, there are downsides! There is added
complexity in creating and understanding the async function, dealing with the pinning (which is
especially painful without <code>alloc</code>), and also, stepping through async functions in the debugger can
be unpleasant.</p><p>There is another more complicated example in <a href="https://github.com/mcbridejc/rust-async-state-machines-demo" target="_blank" rel="noopener noreferrer">the repo</a>, and splitting off the processing into the
future adds a layer of communication: the "main" task cannot pass data into the future once it is
created, so they have to communicate using a shared structure, which has to be Sync (at least if you
want to avoid <code>unsafe</code> code), even though we can actually be sure that the future will never be
executed on another thread.</p>]]></content:encoded>
            <category>rust</category>
            <category>programming</category>
        </item>
    </channel>
</rss>