1<!DOCTYPE html> 2<html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta name="generator" content="Hugo 0.36" /> 5 <meta content="en-US" http-equiv="Content-Language" /> 6 <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /> 8 9 10 <title>HashMismatch</title> 11 <link href='//fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css' /> 12 <link href='//fonts.googleapis.com/css?family=Roboto:400,700,300' rel='stylesheet' type='text/css' /> 13 <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" /> 14 <link rel="stylesheet" type="text/css" href="/css/site.css" /> 15 16 <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png"/> 17 <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png"/> 18 <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png"/> 19 <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png"/> 20 <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png"/> 21 <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png"/> 22 <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png"/> 23 <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png"/> 24 <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/> 25 <link rel="icon" type="image/png" sizes="192x192" href="/android-icon-192x192.png"/> 26 <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/> 27 <link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/> 28 <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/> 29 <link rel="shortcut icon" href="/favicon.ico" /> 30 31
31<script async defer src="https://buttons.github.io/buttons.js"></script>
31 32 33 34 <link href="http://www.hashmismatch.net/index.xml" rel="alternate" type="application/rss+xml" title="HashMismatch" /> 35 <link href="http://www.hashmismatch.net/index.xml" rel="feed" type="application/rss+xml" title="HashMismatch" /> 36 37 38 </head> 39 <body> 40 <header role="banner"> 41 <div class="logo-text"><a href="/index.html" title="HashMismatch">#<span class="ne">!=</span></a></div> 42 43 <div class="icons"> 44 <a href="https://github.com/hashmismatch" title="Github"><i class="fa fa-github"></i></a> 45 </div> 46 </header> 47 <nav> 48 49 When things go mildly wrong 50 51 </nav> 52 53 <div id="content"> 54 55 56 57 <h2 style="line-height: 1.5em"><a href="/libraries/">Software development libraries</a></h2> 58 59 60 61 62 63 64 65<a href="http://www.hashmismatch.net/libraries/packed-struct/"> 66<div class="library_hello" 67 68 style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.0) 0%,rgba(0,0,0,0.2) 70%, rgba(0,0,0,0.8) 100%), url(/libraries/packed_struct_gfx.png);" 69> 70 71 <div class="crate"> 72 packed_struct 73 </div> 74 75 <div class="title"> 76 Bit-level packing and unpacking 77 </div> 78 79</div> 80</a> 81 82 83 84 85 86 87<a href="http://www.hashmismatch.net/libraries/freertos_rs/"> 88<div class="library_hello" 89 90 style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.0) 0%,rgba(0,0,0,0.2) 70%, rgba(0,0,0,0.8) 100%), url(/libraries/demo-hw.jpg);" 91> 92 93 <div class="crate"> 94 freertos_rs 95 </div> 96 97 <div class="title"> 98 A FreeRTOS API for embedded Rust 99 </div> 100 101</div> 102</a> 103 104 105 106 107 108 109<a href="http://www.hashmismatch.net/libraries/terminal-cli/"> 110<div class="library_hello" 111 112 style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.0) 0%,rgba(0,0,0,0.2) 70%, rgba(0,0,0,0.8) 100%), url(/libraries/terminal_cli_gfx.png);" 113> 114 115 <div class="crate"> 116 terminal_cli 117 </div> 118 119 <div class="title"> 120 Interactive command line prompt 121 </div> 122 123</div> 124</a> 125 126 127 128 129 130 <h2><a href="/posts/">Articles</a></h2> 131 132 133 134 135 <div class='post'> 136 <h1><a href="http://www.hashmismatch.net/freertos-meets-rust/">FreeRTOS meets Rust</a></h1> 137 <div class="postdate"><time itemprop="datePublished" pubdate="pubdate" datetime="2016-09-26T09:33:52+02:00">Mon, Sep 26, 2016</time></div> 138 139 140 141<p>The Rust ecosystem has made some cool progress on the embedded development front since my <a href="/pragmatic-bare-metal-rust/">last article</a>. Let’s take a look how we can build a much more ergonomical and safe API to one of the more popular real time operating systems - <a href="http://www.freertos.org/">FreeRTOS</a> - with a full testing and continous integration setup.</p> 142 143<p>To get you going, a snippet from a <a href="https://github.com/hashmismatch/freertos.rs/blob/7a6d19aabb240d2f0cb281664919abe32b6f7d83/qemu_stm32_tests/src/test_sample1.rs">unit test</a> that demonstrates the usage of queues and compute tasks.</p> 144<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#75715e">// A shared queue 145</span><span style="color:#75715e"></span><span style="color:#66d9ef">let</span> queue <span style="color:#f92672">=</span> Arc::new(Queue::new(<span style="color:#ae81ff">10</span>).unwrap()); 146 147<span style="color:#75715e">// Task that consumes integers from the shared queue. Returns the 148</span><span style="color:#75715e">// summed value when a new integer hasn't been posted for 100 ms. 149</span><span style="color:#75715e"></span><span style="color:#66d9ef">let</span> sum_task <span style="color:#f92672">=</span> { 150 <span style="color:#66d9ef">let</span> queue <span style="color:#f92672">=</span> queue.clone(); 151 152 Task::new().name(<span style="color:#e6db74">"sum"</span>).compute(<span style="color:#66d9ef">move</span> <span style="color:#f92672">||</span> { 153 <span style="color:#66d9ef">let</span> <span style="color:#66d9ef">mut</span> sum <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; 154 155 <span style="color:#66d9ef">loop</span> { 156 <span style="color:#66d9ef">if</span> <span style="color:#66d9ef">let</span> Ok(val) <span style="color:#f92672">=</span> queue.receive(Duration::ms(<span style="color:#ae81ff">100</span>)) { 157 sum <span style="color:#f92672">+=</span> val; 158 } <span style="color:#66d9ef">else</span> {
159 <span style="color:#66d9ef">break</span>; 160 } 161 } 162 163 sum 164 }).unwrap() 165}; 166 167<span style="color:#75715e">// Send the integers to the shared queue 168</span><span style="color:#75715e"></span><span style="color:#66d9ef">for</span> i <span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1</span>..<span style="color:#ae81ff">11</span> { 169 queue.send(i, Duration::ms(<span style="color:#ae81ff">15</span>)).unwrap(); 170} 171 172<span style="color:#75715e">// Wait for the compute task to finish the calculation 173</span><span style="color:#75715e"></span><span style="color:#66d9ef">let</span> sum <span style="color:#f92672">=</span> sum_task.into_result(Duration::Infinite).unwrap(); 174 175<span style="color:#75715e">// Check the result 176</span><span style="color:#75715e"></span>assert_eq<span style="color:#f92672">!</span>(<span style="color:#ae81ff">55</span>, sum);</code></pre></div> 177<h2 id="talking-to-freertos">Talking to FreeRTOS</h2> 178 179<p>Most of FreeRTOS’ offical API calls are actually macros that abstract various internal function, so we can’t just directly invoke most of the function calls. So we need an <a href="https://github.com/hashmismatch/freertos.rs/blob/991ee0a4f59842c069f8980e03c58a012aa80e69/shim/freertos_rs.c">inter-op shim</a> written in C that helps us connect Rust and FreeRTOS.</p> 180 181<h2 id="cross-compilation">Cross compilation</h2> 182 183<p>Previously, we had to manually prepare the whole Rust library ecosystem for non-standard cross compilations targets. Rust’s package manager Cargo is thankfully easily extensible and the <a href="https://crates.io/crates/xargo">xargo</a> helper command does the whole job of obtaining the correct sources and preparing an alternate set of Rust libraries (<code>core</code>, <code>alloc</code> and <code>collections</code>) for us. The final output is a set of object files that can be linked together with the target platform’s linker.</p> 184 185<h2 id="base-firmware">Base firmware</h2> 186 187<p>My target board of choice is <a href="http://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-eval-tools/stm32-mcu-eval-tools/stm32-mcu-discovery-kits/stm32f4discovery.html">STM32F4Discovery</a>. ST’s hardware configuration and base firmware generator <a href="http://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-configurators-and-code-generators/stm32cubemx.html">STM32CubeMX</a> greatly helps with setting all the correct clocks, IO ports, timer and other various peripherals. Using a <a href="https://github.com/baoshi/CubeMX2Makefile">project converter</a>, we’re able to use <a href="https://launchpad.net/gcc-arm-embedded">GNU ARM GCC</a> to compile the CubeMX generated project.</p> 188 189<p>The final firmware boots up to the <code>main()</code> written in C, setups the hardware, then hands over the execution to Rust.</p> 190 191<h2 id="unit-tests-and-continous-integration">Unit tests and continous integration</h2> 192 193<p>We’ll make a small compromise by using an emulator instead of the real hardware for continous integration, but it’s an excusable cost cutting for a hobby, open source project. <a href="http://gnuarmeclipse.github.io/qemu/">The GNU ARM Eclipse QEMU</a> provides basic emulation of our development board.</p> 194 195<p>The emulator doesn’t implement many peripherals at the moment. For testing interrupts, we emulate a timer-triggered interrupt by spawning a separate FreeRTOS task and triggering the interrupt programatically. Also the FPU registers aren’t emulated fully, so a hack in FreeRTOS’ scheduler was required to omit the FPU registers while switching the context.</p> 196 197<p>But it all makes it worthwhile when Travis serves you a green tick mark.</p> 198 199<h2 id="standard-api-parity">Standard API parity</h2> 200 201<p>Rust’s standard library provides the same primitives for mutual exclusion, threads and queues, so it would make sense to adopt its namespace and semantics to provide easier usage of other Rust libraries. However, I felt that semantics and requirements for embedded are slightly different so a separate namespace made sense. For embedded application code unit testing on the desktop, an alternative implementation that uses Rust’s standard library could come in handy.</p> 202 203<h2 id="discussion">Discussion</h2> 204 205<p>
205Setting up the development environment is still a mess. Keeping the code generators, open source IDE like Eclipse, Makefiles and Rust in sync takes a lot of mental gymnastics.</p> 206 207<p>Reimplementing FreeRTOS-like functionality in Rust and assembler is a big undertaking, but the ecosystem will probably provide it in time. The one thing that the community seems to have trouble keeping up with is the chip makers and their drivers for peripherals. So I believe that linking to manufacturer’s HAL libraries, with C shims in between - as C developers really like their macros - will be the norm for the foreseeable future.</p> 208 209<hr /> 210 211<p>Github project: <a href="https://github.com/hashmismatch/freertos.rs">FreeRTOS.rs</a> Cargo crate: <a href="https://crates.io/crates/freertos_rs">freertos_rs</a> Documentation: <a href="https://docs.rs/freertos_rs">freertos_rs</a></p> 212 213</div> 214 215 216 217 <h2 style="margin-top: 1.5em;">Archive</h2> 218 219 <ul class="postArchive"> 220 221 <li> 222 <a class="postlink" href="http://www.hashmismatch.net/pragmatic-bare-metal-rust/">Pragmatic Bare Metal Rust</a> 223 </li> 224 225 </ul> 226 227 228 229 230 231 </div> 232 233 <div id="site_copyright"> 234 © 2015-
234<script>document.write(new Date().getFullYear())</script>
234 235 Rudi BenkoviÄ â¢ 236 <a href="https://www.linkedin.com/in/rudi-benkovi%C4%8D-6a59159/">LinkedIn</a> ⢠237 <a href="https://github.com/hashmismatch">GitHub</a> ⢠238 <a href="mailto:[email protected]">Contact</a> 239 </div> 240 241
241<script src="//code.jquery.com/jquery-2.2.1.min.js"></script>
241 242
242<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
242 243 244
244<script>
vendor: 458 bytes, lines 244-252
244 245 (function (i, s, o, g, r, a, m) { 246 i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () { 247 (i[r].q = i[r].q || []).push(arguments) 248 }, i[r].l = 1 * new Date(); a = s.createElement(o), 249 m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m) 250 })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); 251 252 ga('create', '
252UA-63040981-1
vendor: 56 bytes, lines 252-255
252', 'auto'); 253 ga('send', 'pageview'); 254 255
255</script>
255 256 </body> 257</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.