mirror of
https://github.com/lupyuen/lupyuen.github.io.git
synced 2025-01-13 10:18:33 +08:00
1721 lines
No EOL
125 KiB
HTML
1721 lines
No EOL
125 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<link rel="stylesheet" type="text/css" href="/_static/css/banner-styles.css?v=bsmaklHF" />
|
||
<link rel="stylesheet" type="text/css" href="/_static/css/iconochive.css?v=qtvMKcIJ" />
|
||
<link rel="canonical" href="https://lupyuen.org/articles/hosting-embedded-rust-apps-on-apache-mynewt-with-stm32-blue-pill.html" />
|
||
<!-- End Wayback Rewrite JS Include -->
|
||
<title data-rh="true">Hosting Embedded Rust apps on Apache Mynewt with STM32 Blue Pill</title>
|
||
<meta data-rh="true" charset="utf-8" />
|
||
<meta data-rh="true" name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
|
||
<meta data-rh="true" name="theme-color" content="#000000" />
|
||
<meta data-rh="true" property="og:type" content="article" />
|
||
<meta data-rh="true" property="article:published_time" content="2019-08-17T17:17:23.538Z" />
|
||
<meta data-rh="true" name="title" content="Hosting Embedded Rust apps on Apache Mynewt with STM32 Blue Pill" />
|
||
<meta data-rh="true" property="og:title" content="Hosting Embedded Rust apps on Apache Mynewt with STM32 Blue Pill" />
|
||
<meta data-rh="true" property="twitter:title"
|
||
content="Hosting Embedded Rust apps on Apache Mynewt with STM32 Blue Pill" />
|
||
<meta data-rh="true" name="description"
|
||
content="Build IoT devices the smarter, safer way with Rust and Apache Mynewt" />
|
||
<meta data-rh="true" property="og:description"
|
||
content="Build IoT devices the smarter, safer way with Rust and Apache Mynewt" />
|
||
<meta data-rh="true" property="twitter:description"
|
||
content="Build IoT devices the smarter, safer way with Rust and Apache Mynewt" />
|
||
<meta data-rh="true" name="twitter:card" content="summary_large_image" />
|
||
<meta data-rh="true" name="twitter:creator" content="@MisterTechBlog" />
|
||
<meta data-rh="true" name="author" content="Lup Yuen Lee 李立源" />
|
||
<meta data-rh="true" name="robots" content="index,follow" />
|
||
<meta data-rh="true" name="referrer" content="unsafe-url" />
|
||
<meta data-rh="true" name="twitter:label1" value="Reading time" />
|
||
<meta data-rh="true" name="twitter:data1" value="19 min read" />
|
||
<meta property="og:image"
|
||
content="https://lupyuen.github.io/images/legacy2/e1.png">
|
||
|
||
<!-- Begin scripts/rustdoc-header.html: Header for Custom Markdown files processed by rustdoc, like chip8.md -->
|
||
<link rel="alternate" type="application/rss+xml" title="RSS Feed for lupyuen" href="/rss.xml" />
|
||
<link rel="stylesheet" type="text/css" href="../normalize.css">
|
||
<link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle">
|
||
|
||
<link rel="stylesheet" type="text/css" href="../light.css" id="themeStyle">
|
||
<link rel="stylesheet" type="text/css" href="../prism.css">
|
||
<script src="../storage.js"></script><noscript>
|
||
<link rel="stylesheet" href="../noscript.css"></noscript>
|
||
<link rel="shortcut icon" href="../favicon.ico">
|
||
<style type="text/css">
|
||
#crate-search {
|
||
background-image: url("../down-arrow.svg");
|
||
}
|
||
a {
|
||
color: #77d;
|
||
}
|
||
</style>
|
||
<!-- End scripts/rustdoc-header.html -->
|
||
|
||
</head>
|
||
|
||
<body>
|
||
<div id="root">
|
||
<div class="a b c">
|
||
<article>
|
||
<section class="cj ck cl cm ak cn ce n co"></section><span class="r"></span>
|
||
<div>
|
||
<div class="cp u cq cr cs ct"></div>
|
||
<section class="cu cv cw cx cy">
|
||
<div class="cz ak">
|
||
<div class="figure da cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e1.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>What keeps me awake at night? Wondering why our
|
||
microcontrollers (like STM32 Blue Pill above) have become so powerful… that we can’t write powerful
|
||
programs to exploit them</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<div>
|
||
<div id="3c0a" class="ea eb ec bk ed b ee ef eg eh ei ej ek">
|
||
<h1 class="ed b ee el ec">Hosting Embedded Rust apps on Apache Mynewt with STM32 Blue Pill</h1>
|
||
</div>
|
||
<div class="em">
|
||
<div class="n en eo ep eq">
|
||
<div class="o n">
|
||
<div><a rel="noopener"
|
||
href="https://lupyuen.github.io">
|
||
<div class="dd er es">
|
||
<div class="bs n et o p cp eu ev ew ex ey ct"></div>
|
||
|
||
</div>
|
||
</a></div>
|
||
<div class="fa ak r">
|
||
<div class="n">
|
||
<div style="flex:1"><span class="bj b bk bl bm bn r ec q">
|
||
<div class="fb n o fc"><span class="bj dy ds bl di fd fe ff fg fh ec"><a
|
||
class="at au av aw ax ay az ba bb bc fi bf bg bh bi" rel="noopener"
|
||
href="https://lupyuen.github.io">Lup
|
||
Yuen Lee 李立源</a></span>
|
||
|
||
</div>
|
||
</span></div>
|
||
</div><span class="bj b bk bl bm bn r bo bp"><span class="bj dy ds bl di fd fe ff fg fh bo">
|
||
<div><a class="at au av aw ax ay az ba bb bc fi bf bg bh bi" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/hosting-embedded-rust-apps-on-apache-mynewt-with-stm32-blue-pill">
|
||
9 Jun 2019</a> <!-- -->·
|
||
<!-- -->
|
||
<!-- -->19
|
||
<!-- --> min read
|
||
</div>
|
||
</span></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p id="ea07" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Today’s microcontrollers (like
|
||
the <a
|
||
href="http://wiki.stm32duino.com/index.php?title=Blue_Pill"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">STM32 Blue Pill</a>) pack so many
|
||
features in a tiny package… yet few embedded programmers are capable of exploiting the <strong
|
||
class="gj gz">full potential of modern microcontrollers</strong>. Many of us (my IoT students
|
||
included) seem to be stuck in the 1980s —<strong class="gj gz"> painstakingly writing C programs for
|
||
small computers.</strong></p>
|
||
<p id="6d9c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">It’s time to drop our legacy
|
||
programming practices and adopt smarter, safer ways to exploit these microcontrollers… starting with
|
||
<a href="https://mynewt.apache.org/latest/index.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">Apache
|
||
Mynewt</strong></a><strong class="gj gz"> and </strong><a
|
||
href="https://doc.rust-lang.org/stable/book/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong
|
||
class="gj gz">Rust</strong></a><strong class="gj gz">.</strong></p>
|
||
<p id="a684" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Mynewt is a <strong
|
||
class="gj gz">modern realtime operating system</strong> that runs on many microcontroller platforms,
|
||
even on devices with little RAM and ROM like Blue Pill. It has an excellent <a
|
||
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_framework.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">Sensor
|
||
Framework</strong></a> for creating IoT devices.</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e2.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>Sensor Network with Blue Pill, ESP8266,
|
||
nRF24L01 and Mynewt</em></p></figcaption>
|
||
</div>
|
||
<p id="57a2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Stretching Mynewt on Blue Pill to
|
||
the limit, I have created <a class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/build-your-iot-sensor-network-stm32-blue-pill-nrf24l01-esp8266-apache-mynewt-thethings-io">sophisticated
|
||
sensor networks</a> with <a
|
||
href="https://en.wikipedia.org/wiki/Constrained_Application_Protocol"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">CoAP encoding</a> (JSON and <a
|
||
href="https://en.wikipedia.org/wiki/CBOR"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">CBOR</a>), transmitting and
|
||
receiving simultaneously on both ESP8266 and nRF24L01 modules.</p>
|
||
<p id="bbb5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Sadly, Mynewt only supports
|
||
<strong class="gj gz">applications developed in C</strong>, consistent with its frugal origins. But C
|
||
programming is a rare skill today (and C frustrates my IoT students too). What about other languages?
|
||
<a href="https://en.wikipedia.org/wiki/MicroPython"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">MicroPython</a> and <a
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/stm32-blue-pill-dissecting-the-webusb-bootloader-for-makecode">JavaScript</a>
|
||
seem too heavy for a lightweight Mynewt device… <em class="ht">perhaps Rust?</em></p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e3.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Mynewt and Rust: The Perfect Match
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="05d4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In my <a
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://web.archive.org/https://medium.com/coinmonks/coding-the-stm32-blue-pill-with-rust-and-visual-studio-code-b21615d8a20">previous
|
||
experiments</a> with Embedded Rust (<a class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://web.archive.org/https://medium.com/coinmonks/running-rust-and-freertos-on-the-padi-iot-stamp-fb36c5ef4844">including
|
||
this one</a>), I know that Rust flies <strong class="gj gz">light and fast</strong> just like C.
|
||
Rust has <strong class="gj gz">great support in coding tools</strong> like Visual Studio Code, which
|
||
makes it easier to code for newbies.</p>
|
||
<p id="d118" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Rust advocates <strong
|
||
class="gj gz">“Safe Coding”</strong>. Rust<strong class="gj gz"> </strong>disallows bad code that
|
||
may cause our device to crash. <em class="ht">Rust could be the perfect match for Mynewt!</em></p>
|
||
<p id="762a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In this article we’ll mix Mynewt
|
||
with Rust and learn…</p>
|
||
<p id="3f03" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ Why is <strong
|
||
class="gj gz">Rust better than C</strong> for embedded programming</p>
|
||
<p id="fd10" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ How to <strong
|
||
class="gj gz">call C functions from Rust</strong> and vice versa</p>
|
||
<p id="1f26" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ What’s <strong
|
||
class="gj gz">Unsafe Coding</strong> and how to make coding safer</p>
|
||
<p id="2d1e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">4️⃣ How <strong
|
||
class="gj gz">Rust compiles programs</strong></p>
|
||
<p id="fad9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">5️⃣ How to <strong
|
||
class="gj gz">inject Rust code</strong> into the Mynewt build</p>
|
||
<p id="3f3b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">6️⃣ How to <strong
|
||
class="gj gz">install and configure</strong> the Rust and Mynewt code</p>
|
||
<p id="23ff" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">7️⃣ And finally we’ll see an
|
||
actual <strong class="gj gz">Rust application running on Mynewt</strong> with Blue Pill</p>
|
||
<p id="d3b1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s the <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/src"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Rust application code</a> that
|
||
we’ll be running: A sensor application that <strong class="gj gz">polls Blue Pill’s internal
|
||
temperature sensor every 10 seconds</strong> and displays the result…</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure hb hc hd he hf cz">
|
||
<div class="dl r dd">
|
||
<div class="ie r"><iframe
|
||
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FXeRKRI8JYQE%3Ffeature%3Doembed&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DXeRKRI8JYQE&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FXeRKRI8JYQE%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=youtube"
|
||
allowfullscreen="" frameborder="0" height="300" width="400"
|
||
title="Hosting Rust Applications on Apache Mynewt - Code" class="cp t u dh ak"
|
||
scrolling="auto"></iframe></div>
|
||
</div>
|
||
<figcaption><p><em>Walkthrough of the Rust application code
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="5ed5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The complete Rust and Mynewt code
|
||
may be found here…</p>
|
||
<div class="if ig ih ii ij ik"><a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust?source=post_page-----c86b119fe5f----------------------"
|
||
rel="noopener nofollow">
|
||
<section class="in cl cm ak ce n ar io ip iq ir is it iu iv iw ix iy iz ja jb jc">
|
||
<div class="jd n co p je jf">
|
||
<h2 class="bj jg jh bl ec">
|
||
<div class="di il fe ff im fh">lupyuen/stm32bluepill-mynewt-sensor</div>
|
||
</h2>
|
||
</div>
|
||
<div class="jk r">
|
||
<div class="jl r jm jn jo jk jp jq jr"></div>
|
||
</div>
|
||
</section>
|
||
</a></div>
|
||
<blockquote class="js jt ju">
|
||
<p id="7296" class="gh gi ec ht gj b gk gl gm gn go gp gq gr gs gt gu"><em class="bk">💎 </em>Sections
|
||
marked with a diamond are meant for advanced developers. If you’re new to embedded programming, you
|
||
may skip these sections</p>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="6a01" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Embedded Programming in Rust vs
|
||
C</h1>
|
||
<p id="cc7d" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">Why is Rust better than C for
|
||
Embedded Programming? Here’s what I think…</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure hb hc hd he hf cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e4.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>Calling the Mynewt Sensor Listener API: Rust
|
||
Code (left) vs C Code (right)</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="kw">
|
||
<div id="476c" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Rust is Strict and Stubborn</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="1df5" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">Rust syntax is highly similar to
|
||
C. If you’re looking at Rust code for the first time, you may think that Rust is an untyped language
|
||
(like JavaScript) that doesn’t care about the precise types of each variable…</p>
|
||
<p id="b997" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Why would Rust allow <code
|
||
class="dm ln lo lp lq b">let rc = ...</code> without forcing us to declare <code
|
||
class="dm ln lo lp lq b">rc</code> as an <code class="dm ln lo lp lq b">int</code> like in C? Does
|
||
it mean that <code class="dm ln lo lp lq b">rc</code> can change its type from <code
|
||
class="dm ln lo lp lq b">int</code> to <code class="dm ln lo lp lq b">char*</code>?</p>
|
||
<p id="5c81" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Nope, that’s because Rust has <a
|
||
href="https://en.wikipedia.org/wiki/Type_inference"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">Type
|
||
Inference</strong></a> — the Rust compiler analyses our source code and deduces that <code
|
||
class="dm ln lo lp lq b">rc</code> must be an <code class="dm ln lo lp lq b">int</code> (which is
|
||
named <code class="dm ln lo lp lq b">i32</code> in Rust). Why? Because <code
|
||
class="dm ln lo lp lq b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_mgr_api.html#c.sensor_set_poll_rate_ms" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor_set_poll_rate_ms</a>()</code>
|
||
returns an <code class="dm ln lo lp lq b">i32</code> (32-bit integer). So Rust enforces variable types
|
||
as strongly as C, just smarter.</p>
|
||
<p id="a496" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Rust is actually<em class="ht">
|
||
stricter than C</em> — All Rust variables are <a
|
||
href="https://doc.rust-lang.org/stable/book/ch03-01-variables-and-mutability.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">assumed to be constant,
|
||
unchanging, <strong class="gj gz">immutable</strong></a> (<em class="ht">“stubborn”</em>) unless we
|
||
declare the variable as <code class="dm ln lo lp lq b"><strong class="gj gz">mut</strong></code>
|
||
(mutable). Check out the two examples of <code class="dm ln lo lp lq b">mut</code> in the Rust code
|
||
above.</p>
|
||
<p id="2717" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">C is the opposite<em class="ht">
|
||
(“loose and relaxed”). </em>All C variables are mutable unless you declare the variable as <code
|
||
class="dm ln lo lp lq b">const</code>.</p>
|
||
<p id="d797" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Check “<a
|
||
href="https://doc.rust-lang.org/stable/book/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><em class="ht">The Rust
|
||
Programming Language</em></a>” for details.</p>
|
||
<blockquote class="kw">
|
||
<div id="4f66" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Rust is Lean and Lightweight</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="1a4f" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">According to <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/logs/build-application.log#L628-L668"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">this actual build log</a> of our
|
||
combined Rust and Mynewt Sensor application, the entire compiled executable fits into 56 KB of ROM.
|
||
The compiled Rust application and Rust libraries occupy <strong class="gj gz">under 4 KB of
|
||
ROM</strong>. (Most of the ROM space was taken up by the ESP8266 and nRF24L01 drivers written in C.)
|
||
</p>
|
||
<p id="dda4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <strong
|
||
class="gj gz">lightweight nature</strong> of Rust makes it an excellent replacement for embedded C
|
||
programming on devices with constrained resources. Like Blue Pill!</p>
|
||
<blockquote class="kw">
|
||
<div id="5aa3" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Rust Plays Nice with C</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="6f23" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">Rust was designed for <strong
|
||
class="gj gz">low-level systems programming</strong>, like for coding an operating system or web
|
||
browser (<a class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://web.archive.org/https://medium.com/mozilla-tech/a-quantum-leap-for-the-web-a3b7174b3c12">Mozilla
|
||
Firefox</a>). Just like C, Rust is used for bare-metal programming, so it makes sense for <strong
|
||
class="gj gz">Rust and C functions to be interoperable</strong> — We may call C functions from Rust,
|
||
and Rust functions from C. Even pass the same <code class="dm ln lo lp lq b">structs</code> from Rust
|
||
to C and back!</p>
|
||
<p id="03f1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We’ll cover the Rust and C
|
||
interoperability in a while.</p>
|
||
<blockquote class="kw">
|
||
<div id="1341" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Rust is Smarter than C</p>
|
||
</div>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure lr ls lt lu lv cz">
|
||
<div class="dl r dd">
|
||
<div class="ie r"><iframe
|
||
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FeGHxTuRWswY%3Ffeature%3Doembed&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeGHxTuRWswY&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FeGHxTuRWswY%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=youtube"
|
||
allowfullscreen="" frameborder="0" height="300" width="400" title="Rust vs C coding"
|
||
class="cp t u dh ak" scrolling="auto"></iframe></div>
|
||
</div>
|
||
<figcaption><p><em>Visual Studio Code: Rust vs C coding
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="4b92" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Check out this comparison of Rust
|
||
vs C coding in Visual Studio Code. <em class="ht">Why is Rust better than C for coding embedded
|
||
applications?</em></p>
|
||
<p id="daae" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Remember that Rust supports Type
|
||
Inference. The Rust compiler keeps deducing all the types of the variables as we type. So Rust
|
||
provides more helpful <strong class="gj gz">code completion and error highlighting</strong> than C.
|
||
Rust <a
|
||
href="https://lupyuen.github.io/stm32bluepill-mynewt-sensor/rust/mylib/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">generates documentation</a> for
|
||
our functions too.</p>
|
||
<p id="c8b2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This is great for preventing
|
||
programming errors in Rust, especially for beginners. Often in embedded programs we make undocumented
|
||
assumptions and take shortcuts to make the programs run on tiny devices. With Type Inference, Rust can
|
||
<strong class="gj gz">warn new embedded developers about these traps.</strong></p>
|
||
<blockquote class="kw">
|
||
<div id="f7ea" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Rust is Safer than C</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="7042" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">Helping us to write <strong
|
||
class="gj gz">safer, crash-proof programs</strong> is a key feature of Rust, that’s why we see <code
|
||
class="dm ln lo lp lq b">unsafe</code> keywords in the Rust code above. We’ll cover <code
|
||
class="dm ln lo lp lq b">unsafe</code> in a while…</p>
|
||
<blockquote class="kw">
|
||
<div id="9e1d" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">But…</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="02dc" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">Rust is <strong
|
||
class="gj gz">evolving rapidly</strong>, especially for embedded platforms like Blue Pill. A year
|
||
ago I wrote two tutorials on Rust embedded programming…</p>
|
||
<div class="if ig ih ii ij ik"><a rel="noopener"
|
||
href="https://web.archive.org/https://medium.com/coinmonks/coding-the-stm32-blue-pill-with-rust-and-visual-studio-code-b21615d8a20?source=post_page-----c86b119fe5f----------------------">
|
||
<section class="in cl cm ak ce n ar io ip iq ir is it iu iv iw ix iy iz ja jb jc">
|
||
<div class="jd n co p je jf">
|
||
<h2 class="bj jg jh bl ec">
|
||
<div class="di il fe ff im fh">Coding the STM32 Blue Pill with Rust and Visual Studio Code
|
||
</div>
|
||
</h2>
|
||
</div>
|
||
<div class="jk r">
|
||
<div class="lw r jm jn jo jk jp jq jr"></div>
|
||
</div>
|
||
</section>
|
||
</a></div>
|
||
<div class="if ig ih ii ij ik"><a rel="noopener"
|
||
href="https://web.archive.org/https://medium.com/coinmonks/running-rust-and-freertos-on-the-padi-iot-stamp-fb36c5ef4844?source=post_page-----c86b119fe5f----------------------">
|
||
<section class="in cl cm ak ce n ar io ip iq ir is it iu iv iw ix iy iz ja jb jc">
|
||
<div class="jd n co p je jf">
|
||
<h2 class="bj jg jh bl ec">
|
||
<div class="di il fe ff im fh">Running Rust and FreeRTOS on the PADI IoT Stamp</div>
|
||
</h2>
|
||
</div>
|
||
<div class="jk r">
|
||
<div class="lx r jm jn jo jk jp jq jr"></div>
|
||
</div>
|
||
</section>
|
||
</a></div>
|
||
<p id="aa17" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">…And they have already become
|
||
obsolete.</p>
|
||
<p id="0e43" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="ht">Be very patient if
|
||
things don’t work quite right in Rust.</em> I may not have the answer for some deep issues, but I’m
|
||
confident that Rust maintainers will have the answer for us someday.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="af57" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Mixing Mynewt and Rust</h1>
|
||
<p id="b102" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">Built in C, Mynewt is a modern,
|
||
well-designed operating system for microcontrollers. Rust is a modern, smarter, safer programming
|
||
language for embedded systems. <em class="ht">How shall we enjoy the best of both worlds — Mynewt and
|
||
Rust? </em>I propose to…</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e5.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>Layering Rust above Mynewt</em></p></figcaption>
|
||
</div>
|
||
<p id="1dc3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong class="gj gz">Leave
|
||
the Mynewt operating system untouched</strong>, in C. Same goes for Mynewt drivers and libraries,
|
||
since they were coded by experienced C programmers.</p>
|
||
<p id="ef35" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong class="gj gz">Expose
|
||
the popular Mynewt APIs </strong>through safe Rust interop libraries</p>
|
||
<p id="3f78" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <strong class="gj gz">Allow
|
||
Rust applications to be hosted</strong> on Mynewt with these exposed APIs</p>
|
||
<p id="de5e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">So new embedded developers (and
|
||
my IoT students) can start <strong class="gj gz">coding Mynewt applications in Rust, the smarter,
|
||
safer way</strong>. <em class="ht">No more crashing pointers. Yay!</em></p>
|
||
<p id="8979" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To host a Rust application on
|
||
Mynewt, we need to be sure that C and Rust can really call each other seamlessly…</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e6.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>Rust and C interoperability</em></p></figcaption>
|
||
</div>
|
||
<p id="768d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ Rust must allow <strong
|
||
class="gj gz">importing of Mynewt’s C API.</strong> So Rust functions must be able to call C
|
||
functions: <br /><strong class="gj gz">Rust ⟶ C</strong></p>
|
||
<p id="1449" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ Rust must allow <strong
|
||
class="gj gz">callbacks from Mynewt’s C API</strong>. So Rust must allow its functions to be called
|
||
from C functions: <br /><strong class="gj gz">Rust ⟵ C</strong></p>
|
||
<p id="3055" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ Rust must allow <code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">structs</strong></code><strong class="gj gz"> to be
|
||
passed from Rust to C and back</strong>: <br /><strong class="gj gz">Rust ⟵📦⟶ C</strong></p>
|
||
<p id="e1b7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Fortunately, Rust fulfils all the
|
||
criteria above. For example, to import the following <a
|
||
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_api.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Mynewt Sensor API </a>functions
|
||
into our Rust application…</p>
|
||
<p id="4020" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">int <a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_mgr_api.html#c.sensor_set_poll_rate_ms" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">sensor_set_poll_rate_ms</strong></a>(const char *<em class="ht"> devname</em>, uint32_t<em class="ht"> poll_rate</em>)</code>
|
||
</p>
|
||
<p id="a29b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">struct <a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_api.html#c.sensor" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor</a>* <a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_mgr_api.html#c.sensor_mgr_find_next_bydevname" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">sensor_mgr_find_next_bydevname</strong></a>(const char *<em class="ht"> devname</em>, struct <a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_api.html#c.sensor" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor</a>*<em class="ht"> prev_cursor</em>)</code>
|
||
</p>
|
||
<p id="381c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">int <a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">sensor_register_listener</strong></a>(struct <a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_api.html#c.sensor" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor</a> *<em class="ht"> sensor</em>, struct sensor_listener *<em class="ht"> listener</em>)</code>
|
||
</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm mc md me mf hr">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/4086dff9b067959c5e337d1c164eea96.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust code to import Mynewt Sensor API. From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L35-L62"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L35-L62</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="556a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">…We just compile this Rust code
|
||
with our Rust application, then we can call the Mynewt functions as though they were Rust functions!
|
||
</p>
|
||
<p id="c970" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">💎 <em class="ht">How did we
|
||
derive the Rust import declarations above from the Mynewt C declarations? This is explained in the
|
||
section “Calling C from Rust and back” below.</em></p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="f557" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Is This Code Unsafe?</h1>
|
||
<p id="8911" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu"><em class="ht">Question</em>:
|
||
What’s wrong with this C function that calls the Mynewt API <code
|
||
class="dm ln lo lp lq b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor_register_listener</a>()</code>?
|
||
</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/f934d3539f4b5e79e6b0c30633f73b92.js"></script></p>
|
||
|
||
|
||
</div>
|
||
<p id="dfc3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="ht">Answer</em>: <code
|
||
class="dm ln lo lp lq b">listener</code> is a variable created on the stack frame for <code
|
||
class="dm ln lo lp lq b">start_sensor_listener()</code>. When passed to <code
|
||
class="dm ln lo lp lq b">sensor_register_listener()</code>, the <code
|
||
class="dm ln lo lp lq b">listener</code> is appended directly to the global list of sensor
|
||
listeners, without copying.</p>
|
||
<p id="1ea7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When <code
|
||
class="dm ln lo lp lq b">start_sensor_listener()</code> returns, the stack frame is reused by other
|
||
functions and the <code class="dm ln lo lp lq b">listener</code> may contain garbage. When the sensor
|
||
is polled 10 seconds later, Mynewt fetches the garbled <code class="dm ln lo lp lq b">listener</code>
|
||
to call the listener function. Which results in a catastrophic device failure. <em class="ht">One IoT
|
||
Device Down!</em></p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e7.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>Bewildering variable choices for the C
|
||
programmer</em></p></figcaption>
|
||
</div>
|
||
<p id="8b23" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This is one key reason why my IoT
|
||
students find C programming so hard…<em class="ht"> Every time we define a variable in C, we need to
|
||
pick wisely whether it should be a</em> 1️⃣ <strong class="gj gz">Static Variable, 2️⃣ Stack
|
||
Variable or 3️⃣ Heap Variable.</strong></p>
|
||
<p id="e960" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Choosing the wrong one will have
|
||
<em class="ht">dire consequences</em>… that’s why Rust calls this “<strong
|
||
class="gj gz">Unsafe</strong>” code.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="385c" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Unsafe Coding in Rust</h1>
|
||
<p id="c688" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">Rust doesn’t prevent us from
|
||
writing unsafe code though — it requires us to flag the code as unsafe using the <code
|
||
class="dm ln lo lp lq b">unsafe</code> keyword. Otherwise the Rust compiler politely terminates and
|
||
refuses to generate any unsafe executables, for our safety.</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/dcd83bcb334cee1506315bb8ccdc747a.js"></script></p>
|
||
|
||
|
||
</div>
|
||
<p id="6f51" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In the Rust code above we are
|
||
required to ring the alarm bells and flag as <code class="dm ln lo lp lq b">unsafe</code> the call to
|
||
<code
|
||
class="dm ln lo lp lq b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor_register_listener</a>()</code>
|
||
because…</p>
|
||
<p id="3d0e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ We are <strong
|
||
class="gj gz">passing the address</strong> of the <code class="dm ln lo lp lq b">listener</code> to
|
||
a function <code class="dm ln lo lp lq b">sensor_register_listener()</code>. Which may cause problems
|
||
if the <code class="dm ln lo lp lq b">listener</code> was allocated incorrectly (like on the stack).
|
||
<code class="dm ln lo lp lq b">&mut listener</code> is equivalent to <code
|
||
class="dm ln lo lp lq b">&listener</code> in C, just that it also declares to Rust that the
|
||
<code class="dm ln lo lp lq b">listener</code> contents may change (mutable).</p>
|
||
<p id="e237" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <code
|
||
class="dm ln lo lp lq b">sensor_register_listener()</code> is a C function defined by Mynewt, that
|
||
we have imported into Rust. <strong class="gj gz">All imported functions must be flagged as
|
||
</strong><code class="dm ln lo lp lq b"><strong class="gj gz">unsafe</strong></code> because, as we
|
||
know, C functions are capable of doing really weird things.</p>
|
||
<p id="08c0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But we don’t really want <code
|
||
class="dm ln lo lp lq b">unsafe</code> alarm bells to ring in our heads every time we call the
|
||
Mynewt API. <em class="ht">Is there a safer way to silence the alarms?</em></p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="ba09" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Safer Coding in Rust</h1>
|
||
<p id="7fa9" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">The safer way to call <code
|
||
class="dm ln lo lp lq b">unsafe</code> Mynewt APIs in Rust is to <a
|
||
href="https://doc.rust-lang.org/1.6.0/book/ffi.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">create
|
||
wrapper functions</strong></a> to check the parameters and the return values.</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/d7955a8edfe11422424c0d6c37b7e22d.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="30e3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Check this out… we can now
|
||
register a sensor listener without flagging as <code class="dm ln lo lp lq b">unsafe</code>! And the
|
||
listener was allocated on the stack!</p>
|
||
<p id="2453" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This is the <em
|
||
class="ht">perfect kind of API</em> that my IoT students should be calling, without fear of <em
|
||
class="ht">crashing their devices</em>. What is the magic that makes this happen?</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/c41e3fb94adeaaba69c986817792dc56.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em><a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="0404" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s how we created <code
|
||
class="dm ln lo lp lq b">register_listener()</code> as the safe version of the <code
|
||
class="dm ln lo lp lq b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor_register_listener</a>()</code>
|
||
API in Mynewt… <code class="dm ln lo lp lq b">register_listener()</code> makes a <strong
|
||
class="gj gz">local static copy of the listener</strong>, and passes the local copy to the unsafe
|
||
<code class="dm ln lo lp lq b">sensor_register_listener()</code>. So even if the listener was created
|
||
on the stack, we are actually passing a static copy to the Mynewt API. Which won’t crash the device.
|
||
</p>
|
||
<p id="620f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We have created a simple Rust
|
||
wrapper that reuses the same types used by the Mynewt API. (That’s why <code
|
||
class="dm ln lo lp lq b">register_listener()</code> returns an integer as the result code.) But Rust
|
||
APIs generally use a different convention to return results — <a
|
||
href="https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">the </a><code
|
||
class="dm ln lo lp lq b"><a href="https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Result</a></code><a
|
||
href="https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"> type</a>. We’ll cover this in the
|
||
next article.</p>
|
||
<blockquote class="js jt ju">
|
||
<p id="a898" class="gh gi ec ht gj b gk gl gm gn go gp gq gr gs gt gu"><em class="bk">💎 </em>This
|
||
implementation looks simplistic… what if we need more sensor listeners? But in reality our device
|
||
RAM is highly constrained and we should plan in advance how many sensor listeners we really need
|
||
(and set it as a <code class="dm ln lo lp lq b">#define</code>). Then we create an array of
|
||
listeners that’s allocated by <code class="dm ln lo lp lq b">register_listener()</code>.</p>
|
||
<p id="bbc0" class="gh gi ec ht gj b gk gl gm gn go gp gq gr gs gt gu">What about allocating listeners
|
||
on the heap? That could be a good solution but I’m not keen on using the heap on constrained devices
|
||
(because we never know when we’ll run out of heap space). The <code
|
||
class="dm ln lo lp lq b"><a href="https://docs.rust-embedded.org/book/collections/" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">alloc</a></code><a
|
||
href="https://docs.rust-embedded.org/book/collections/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"> heap allocator</a> needs to be
|
||
implemented for our Rust environment.</p>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="99fb" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">The Typical Rust Build</h1>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e8.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>Files involved in the Rust build</em></p></figcaption>
|
||
</div>
|
||
<p id="9c3d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To understand how we merged the
|
||
Rust build with Mynewt, let’s look at the typical Rust build process.</p>
|
||
<p id="f8d6" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The following files are present
|
||
in a standard Rust build. You can find them in your <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">stm32bluepill-mynewt-sensor</a></code>
|
||
folder too…</p>
|
||
<p id="9187" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/Cargo.toml" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">Cargo.toml</strong></a></code>:
|
||
Just like building a typical Rust application, in Mynewt we run the command <code
|
||
class="dm ln lo lp lq b">cargo build</code> to build our embedded Rust application.</p>
|
||
<p id="76ed" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">cargo</code> performs the build according to the settings file <code
|
||
class="dm ln lo lp lq b">Cargo.toml</code>. This file must be present at the root of the workspace
|
||
folder.</p>
|
||
<p id="41d0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We’ll check the contents of <code
|
||
class="dm ln lo lp lq b">Cargo.toml</code> in a while.</p>
|
||
<p id="5e65" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/.cargo/config" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">.cargo/config</strong></a></code>:
|
||
Our Rust build is for an embedded platform: STM32 Blue Pill. The target platform is specified in this
|
||
file.</p>
|
||
<p id="9a91" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We’ll check the contents of <code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">.cargo/config</strong></code> in a while.</p>
|
||
<p id="f7eb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/src" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">src</strong></a></code>:
|
||
This folder contains the Rust source code. <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/lib.rs" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">lib.rs</strong></a></code>
|
||
is the main Rust module that pulls in the other Rust files for the build (via the <code
|
||
class="dm ln lo lp lq b">mod</code> declaration).</p>
|
||
<p id="7fc2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">4️⃣ <code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">target/thumbv7m-none-eabi/debug</strong></code>: The
|
||
<code class="dm ln lo lp lq b">cargo build</code> command compiles the <code
|
||
class="dm ln lo lp lq b">src</code> files and generates in this <code
|
||
class="dm ln lo lp lq b">debug</code> folder the Rust executable or library (according to <code
|
||
class="dm ln lo lp lq b">Cargo.toml</code>).</p>
|
||
<div class="figure hb hc hd he hf cz cl cm paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
<div class="figure du cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e9.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Compiled Rust code in <code
|
||
class="dm ln lo lp lq b">libmylib.rlib</code></em></p></figcaption>
|
||
</div>
|
||
<p id="dad5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In our build, <code
|
||
class="dm ln lo lp lq b">cargo</code> generates a library archive file <code
|
||
class="dm ln lo lp lq b">libmylib.rlib</code>. If we peek at the contents of the archive file
|
||
…<br /> <code
|
||
class="dm ln lo lp lq b">arm-none-eabi-ar t target/thumbv7m-none-eabi/debug/libmylib.rlib</code><br />…we’ll
|
||
see that it contains <code class="dm ln lo lp lq b">*.o</code> object files, the compiled Rust code.
|
||
</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e10.png" /></p>
|
||
|
||
|
||
</div>
|
||
<p id="4a06" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But the files in this <code
|
||
class="dm ln lo lp lq b">debug</code> folder exclude the external Rust libraries called by our
|
||
application (like <code
|
||
class="dm ln lo lp lq b"><a href="https://crates.io/crates/cty" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">cty</a></code>
|
||
and <code
|
||
class="dm ln lo lp lq b"><a href="https://crates.io/crates/cstr_core" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">cstr_core</a></code>).
|
||
</p>
|
||
<p id="53d4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To include the external Rust
|
||
libraries for the Mynewt build, we need to look one level deeper: <code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">debug/deps</strong></code></p>
|
||
<p id="3421" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This folder contains the compiled
|
||
<code class="dm ln lo lp lq b">*.rlib</code> archive files for our Rust application (<code
|
||
class="dm ln lo lp lq b">libmylib-*.rlib</code>) as well as external Rust libraries.</p>
|
||
<p id="fbb9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">As we’ll see later, all the <code
|
||
class="dm ln lo lp lq b">*.rlib</code> files in <code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">debug/deps</strong></code> will be injected into the
|
||
Mynewt build.</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e11.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Typical Rust Build</em></p></figcaption>
|
||
</div>
|
||
<p id="70d3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">5️⃣ <strong class="gj gz">Rust
|
||
Core Library </strong><code
|
||
class="dm ln lo lp lq b"><a href="https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/libcore-for-low-level-rust.html" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">libcore</strong></a></code>:
|
||
There’s one important Rust library that’s missing — the Rust Core Library <code
|
||
class="dm ln lo lp lq b">libcore</code>. This library contains the fundamental code needed to
|
||
implement the <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/logs/libcore.S"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">core Rust functions</a>: data
|
||
structures, math, panicking, text formatting, …</p>
|
||
<p id="5627" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">libcore</code> is automatically included during the <code
|
||
class="dm ln lo lp lq b">cargo</code> build if we use <code class="dm ln lo lp lq b">cargo</code> to
|
||
generate the executable. But here we are using Mynewt to generate the executable, so we need to add
|
||
<code class="dm ln lo lp lq b">libcore</code> ourselves.</p>
|
||
<p id="e182" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Where is <code
|
||
class="dm ln lo lp lq b">libcore</code> located? It’s actually located together with the Rust
|
||
compiler (not with the <code class="dm ln lo lp lq b">cargo</code> installation). <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L91-L109"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Our build script</a> runs this
|
||
command to get the location…</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/b2ce2714a6849c7e992f1606468cbc80.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Locating the Rust Core Library libcore. From
|
||
<a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L91-L109"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L91-L109</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="7220" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">On my Mac, <code
|
||
class="dm ln lo lp lq b">libcore</code> is located at <code
|
||
class="dm ln lo lp lq b">/Users/Luppy/.rustup/toolchains/nightly-2019–05–22-x86_64-apple-darwin/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e6b0ad9835323d10.rlib</code>
|
||
</p>
|
||
<p id="c6ac" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that <code
|
||
class="dm ln lo lp lq b">libcore</code> is specific to the target platform (Blue Pill is <code
|
||
class="dm ln lo lp lq b">thumbv7m-none-eabi</code>). We’ll link the <code
|
||
class="dm ln lo lp lq b">libcore</code> library in the Mynewt build.</p>
|
||
<blockquote class="js jt ju">
|
||
<p id="968c" class="gh gi ec ht gj b gk gl gm gn go gp gq gr gs gt gu"><em class="bk">💎 </em>The
|
||
disassembled code for our Rust application is <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/logs/libmylib-demangle.S"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">available here</a>. The
|
||
disassembled code for <code class="dm ln lo lp lq b">libcore</code> is <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/logs/libcore.S"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">available here</a>.</p>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="a9a7" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Rust Build Settings</h1>
|
||
<p id="c42e" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">Let’s look at the simple Rust
|
||
build settings for our project (which was inspired by <a
|
||
href="https://rust-embedded.github.io/book/start/qemu.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">this sample</a>)…</p>
|
||
<blockquote class="kw">
|
||
<div id="9f39" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo"><a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/Cargo.toml"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong
|
||
class="az">Cargo.toml</strong></a></p>
|
||
</div>
|
||
</blockquote>
|
||
<div class="figure lr ls lt lu lv cz dr hg cd hh hi hj hk hl ba hm mc md me mf hr">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/3d1afad3c9827e3e7eb9ba04f20877aa.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust build settings. From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/Cargo.toml"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/Cargo.toml</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="74f7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here we indicate to <code
|
||
class="dm ln lo lp lq b">cargo</code> that we’re generating a library <code
|
||
class="dm ln lo lp lq b">[lib]</code> (instead of an executable <code
|
||
class="dm ln lo lp lq b">[bin]</code>).</p>
|
||
<p id="acaf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To keep the ROM size small, we
|
||
have included only a few small libraries.</p>
|
||
<p id="a5f0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This <code
|
||
class="dm ln lo lp lq b">Cargo.toml</code><strong class="gj gz"> </strong>produces the compiled Rust
|
||
library <code class="dm ln lo lp lq b">libmylib.rlib</code> that we’ll link with Mynewt.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure hb hc hd he hf cz mt mu paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="kw">
|
||
<div id="bef0" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo"><code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/.cargo/config" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="az">.cargo/config</strong></a></code>
|
||
</p>
|
||
</div>
|
||
</blockquote>
|
||
<div class="figure lr ls lt lu lv cz dr hg cd hh hi hj hk hl ba hm mc md me mf hr">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/c100373c4a862e363268ea970d4e8c61.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust target settings. From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/.cargo/config"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/.cargo/config</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="a604" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here we select the target
|
||
platform for the Rust compiler.</p>
|
||
<p id="ce0d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">STM32 Blue Pill runs on an Arm
|
||
Cortex-M3 processor (which is based on the <a
|
||
href="https://en.wikipedia.org/wiki/ARM_Cortex-M#Cortex-M3"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">ARMv7-M architecture</a>), so we
|
||
have chosen the target <code class="dm ln lo lp lq b">thumbv7m-none-eabi</code></p>
|
||
<p id="7f6b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">cargo build</code> will then generate compiled code in <code
|
||
class="dm ln lo lp lq b">libmylib.rlib </code>that will run on our Blue Pill.</p>
|
||
<div class="figure hb hc hd he hf cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
<p id="00e2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">As we have seen, <strong
|
||
class="gj gz">we haven’t changed anything in the Rust </strong><code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">cargo build</strong></code><strong class="gj gz">
|
||
process</strong>. We used the standard <code class="dm ln lo lp lq b">cargo build</code> command to
|
||
generate a Rust library <code class="dm ln lo lp lq b">libmylib.rlib</code> for our Rust application.
|
||
</p>
|
||
<p id="24e5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The integration of Rust with
|
||
Mynewt is actually done by <strong class="gj gz">our custom build script that injects the compiled
|
||
Rust files into the Mynewt build</strong>. Before going into the integration details, let’s learn
|
||
about the Mynewt build…</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<div class="figure hb hc hd he hf cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e12.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Typical Mynewt Build</em></p></figcaption>
|
||
</div>
|
||
<h1 id="01cf" class="ke kf ec bk bj jg kg mx ki my kk mz km na ko nb kq">The Typical Mynewt Build</h1>
|
||
<p id="9661" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">The normal Mynewt build command
|
||
<code class="dm ln lo lp lq b">newt build</code> compiles some C and assembly files from these
|
||
folders…</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e13.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Libraries generated by newt build</em></p></figcaption>
|
||
</div>
|
||
<p id="abf0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/apps/my_sensor_app" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">apps/my_sensor_app</strong></a></code>:
|
||
Our custom C application for Mynewt</p>
|
||
<p id="fb5a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/libs" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">libs</strong></a></code>:
|
||
Custom drivers (e.g. ESP8266) and libraries (e.g. Sensor Network) for Mynewt</p>
|
||
<p id="dff8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">repos</strong></code>: Mynewt OS source code</p>
|
||
<p id="a9a1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">newt build</code> compiles each source module (e.g. <code
|
||
class="dm ln lo lp lq b">my_sensor_app</code>, <code class="dm ln lo lp lq b">esp8266</code>) into a
|
||
separate <code class="dm ln lo lp lq b">*.a</code> library (e.g. <code
|
||
class="dm ln lo lp lq b">apps_my_sensor_app.a</code>, <code
|
||
class="dm ln lo lp lq b">libs_esp8266.a</code>), located at <code
|
||
class="dm ln lo lp lq b">bin/targets/bluepill_my_sensor</code></p>
|
||
<p id="f3cb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">newt build</code> links the <code class="dm ln lo lp lq b">*.a</code>
|
||
libraries together to create the Blue Pill executable image <code
|
||
class="dm ln lo lp lq b">/bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf</code>
|
||
</p>
|
||
<p id="c250" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This is the image that get
|
||
flashed into the Blue Pill ROM.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="cz ak">
|
||
<div class="figure hb hc hd he hf cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e14.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Combined build with Rust and Mynewt: <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L1"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="0623" class="ke kf ec bk bj jg kg mx ki my kk mz km na ko nb kq">Merging the Rust build with
|
||
Mynewt</h1>
|
||
<p id="a00c" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">To host a Rust application on
|
||
Mynewt, we just need to inject three pieces of compiled code into the Mynewt build…</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e15.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Overwriting libs_rust_app.a by the compiled
|
||
Rust application and libraries</em></p></figcaption>
|
||
</div>
|
||
<p id="6fb8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong
|
||
class="gj gz">Compiled Rust application</strong>: <code
|
||
class="dm ln lo lp lq b">libmylib.rlib</code></p>
|
||
<p id="ec2d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong
|
||
class="gj gz">Compiled external Rust libraries</strong>: <code
|
||
class="dm ln lo lp lq b">target/thumbv7m-none-eabi/debug/deps/*.rlib.</code> This folder also
|
||
contains <code class="dm ln lo lp lq b">libmylib.rlib</code></p>
|
||
<p id="1973" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <strong class="gj gz">Rust
|
||
Core Library </strong><code class="dm ln lo lp lq b"><strong class="gj gz">libcore</strong></code>:
|
||
<code
|
||
class="dm ln lo lp lq b">~/.rustup/toolchains/nightly-*/lib/rustlib/thumbv7m-none-eabi/lib/libcore-*.rlib</code>
|
||
</p>
|
||
<p id="57fb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To do that, we have a super build
|
||
script <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">scripts/build-app.sh</strong></a></code>
|
||
that runs the Rust <code class="dm ln lo lp lq b">cargo build</code> command and injects the above
|
||
files at these Mynewt build locations…</p>
|
||
<p id="c88e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong class="gj gz">Rust
|
||
application and external Rust libraries</strong>: Copy and overwrite <code
|
||
class="dm ln lo lp lq b">bin/targets/bluepill_my_sensor/app/libs/rust_app/libs_rust_app.a</code></p>
|
||
<p id="8472" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong class="gj gz">Rust
|
||
</strong><code class="dm ln lo lp lq b"><strong class="gj gz">libcore</strong></code>: Copy and
|
||
overwrite <code
|
||
class="dm ln lo lp lq b">bin/targets/bluepill_my_sensor/app/libs/rust_libcore/libs_rust_libcore.a</code>
|
||
</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm hn ho hp hq hr paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e16.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>rust_app and rust_libcore are empty stub
|
||
libraries</em></p></figcaption>
|
||
</div>
|
||
<p id="4f1a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">What are <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/libs/rust_app" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">rust_app</strong></a></code>
|
||
and <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/libs/rust_libcore" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">rust_libcore</strong></a></code>?
|
||
These are custom stub libraries that we added to Mynewt at <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/libs/rust_app" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">libs/rust_app</a></code>
|
||
and <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/libs/rust_libcore" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">libs/rust_libcore</a></code>.
|
||
No meaningful code inside, just stubs.</p>
|
||
<p id="9cc2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But because we instructed Mynewt
|
||
to <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/apps/my_sensor_app/pkg.yml#L17-L21"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">include them as part of the Mynewt
|
||
build</a>, Mynewt compiles them and generates the tiny libraries <code
|
||
class="dm ln lo lp lq b">libs_rust_app.a</code> and <code
|
||
class="dm ln lo lp lq b">libs_rust_libcore.a</code></p>
|
||
<p id="0d39" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Which gives us the perfect
|
||
opportunity to substitute <code class="dm ln lo lp lq b">libs_rust_app.a</code> and <code
|
||
class="dm ln lo lp lq b">libs_rust_libcore.a</code> with our compiled Rust code.</p>
|
||
<p id="3e22" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Our super build script <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L77-L83"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">overwrites </a><code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L77-L83" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">libs_rust_app.a</a></code>
|
||
with the compiled Rust application and libraries, and <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L91-L109"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">overwrites </a><code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L91-L109" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">libs_rust_libcore.a</a></code>
|
||
with the Rust <code class="dm ln lo lp lq b">libcore</code> library. So when <code
|
||
class="dm ln lo lp lq b">newt build</code> links all the <code class="dm ln lo lp lq b">*.a</code>
|
||
libraries, the <strong class="gj gz">Rust code gets injected into </strong><code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">my_sensor_app.elf</strong></code>, which will be
|
||
flashed into the Blue Pill ROM. Sneaky!</p>
|
||
<div class="figure hb hc hd he hf cz dr hg cd hh hi hj hk hl ba hm mc md me mf hr">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/4b95ee72af032bee9d371069b7556608.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L51-L83"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L51-L83</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="c238" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But how do we replace <code
|
||
class="dm ln lo lp lq b">libs_rust_app.a</code> by multiple <code
|
||
class="dm ln lo lp lq b">*.rlib</code> libraries: <code
|
||
class="dm ln lo lp lq b">libmylib.rlib</code> + <code class="dm ln lo lp lq b">libcty.rlib</code> +
|
||
<code class="dm ln lo lp lq b">libcstr_core.rlib</code> + ...?</p>
|
||
<p id="fa2a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Our <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/scripts/build-app.sh#L51-L83"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">super build script</a> extracts
|
||
the <code class="dm ln lo lp lq b">*.o</code> object files from every <code
|
||
class="dm ln lo lp lq b">*.rlib</code> file and archives them into a single <code
|
||
class="dm ln lo lp lq b">rustlib.a</code> library.</p>
|
||
<p id="fceb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">That’s how we create the Mynewt
|
||
ROM for Blue Pill that includes the Rust application and libraries!</p>
|
||
<div class="figure hb hc hd he hf cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
<p id="6338" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This video explains the combined
|
||
Rust and Mynewt build…</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure hb hc hd he hf cz">
|
||
<div class="dl r dd">
|
||
<div class="ie r"><iframe
|
||
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FQTTqRlsiBfk%3Ffeature%3Doembed&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DQTTqRlsiBfk&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FQTTqRlsiBfk%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=youtube"
|
||
allowfullscreen="" frameborder="0" height="300" width="400"
|
||
title="Hosting Rust Applications on Apache Mynewt - Build" class="cp t u dh ak"
|
||
scrolling="auto"></iframe></div>
|
||
</div>
|
||
<figcaption><p><em>Building the combined Rust and Mynewt code
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="js jt ju">
|
||
<p id="83a9" class="gh gi ec ht gj b gk gl gm gn go gp gq gr gs gt gu"><em class="bk">💎 </em>The
|
||
complete Rust and Mynewt build log is <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/logs/build-application.log#L1"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">available here</a>. The
|
||
disassembled code for our Mynewt ROM image is <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/logs/my_sensor_app.elf.lst"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">available here</a>.</p>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="48c2" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Installation and Configuration
|
||
</h1>
|
||
<p id="b392" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">If you have the <a
|
||
href="http://wiki.stm32duino.com/index.php?title=Blue_Pill"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">STM32 Blue Pill</a> or <a
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/super-blue-pill-like-stm32-blue-pill-but-better">Super
|
||
Blue Pill</a> and you wish to install and configure the Rust and Mynewt demo code, <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/README.md"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">follow the instructions here</a>.
|
||
The steps are quite lengthy and you may run into hiccups, so I don’t recommend this if you’re new to
|
||
embedded development.</p>
|
||
<p id="878e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Make sure that you’re using the
|
||
<code class="dm ln lo lp lq b">rust</code> branch of the code, not the <code
|
||
class="dm ln lo lp lq b">master</code> branch (that was used in previous articles)…</p>
|
||
<p id="3b88" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/<strong class="gj gz">rust</strong></a></code>
|
||
</p>
|
||
<p id="64a9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Verify that the <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/README.md" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">README.md</a></code>
|
||
says…</p>
|
||
<pre
|
||
class="hb hc hd he hf nj nk nl"><span id="8033" class="nm kf ec bk lq b ds nn no r np">Note: This is the rust branch that contains a Rust application hosted on Mynewt</span></pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="afdc" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Conclusion</h1>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure hb hc hd he hf cz">
|
||
<div class="dl r dd">
|
||
<div class="ie r"><iframe
|
||
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FPj3pl6GaztU%3Ffeature%3Doembed&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DPj3pl6GaztU&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FPj3pl6GaztU%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=youtube"
|
||
allowfullscreen="" frameborder="0" height="300" width="400"
|
||
title="Hosting Rust Applications on Apache Mynewt - Run" class="cp t u dh ak"
|
||
scrolling="auto"></iframe></div>
|
||
</div>
|
||
<figcaption><p><em>Running our Rust application on Mynewt
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="51c3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s a video of our Rust
|
||
application, hosted on Mynewt, running on an actual Blue Pill. It works as expected: Reading the Blue
|
||
Pill’s internal temperature sensor every 10 seconds and displaying the results— <em
|
||
class="ht">Yay!</em></p>
|
||
<p id="683e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">With some simple build
|
||
integration, we have proven that it’s indeed possible to <strong class="gj gz">host Rust applications
|
||
on Mynewt</strong> (and probably other embedded operating systems too). And it requires <strong
|
||
class="gj gz">very little RAM and ROM to support embedded Rust.</strong></p>
|
||
<p id="12b7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Perhaps the bigger challenge is
|
||
to <strong class="gj gz">design a Rust API for Mynewt that’s safe and easy to use.</strong></p>
|
||
<p id="a0cf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In the meantime, what we have
|
||
created is probably sufficient for new embedded developers (and my students) to <strong
|
||
class="gj gz">create IoT devices in Rust and Mynewt without fear of memory corruption</strong>. <em
|
||
class="ht">Saving the world from unsafe embedded C programming… one microstep at a time!</em></p>
|
||
<p id="e064" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Check out the latest article on
|
||
Visual Embedded Rust…</p>
|
||
<div class="if ig ih ii ij ik"><a rel="noopener"
|
||
href="https://lupyuen.github.io/articles/visual-embedded-rust-programming-with-visual-studio-code">
|
||
<section class="in cl cm ak ce n ar io ip iq ir is it iu iv iw ix iy iz ja jb jc">
|
||
<div class="jd n co p je jf">
|
||
<h2 class="bj jg jh bl ec">
|
||
<div class="di il fe ff im fh">Visual Embedded Rust Programming with Visual Studio Code</div>
|
||
</h2>
|
||
</div>
|
||
<div class="jk r">
|
||
<div class="nq r jm jn jo jk jp jq jr"></div>
|
||
</div>
|
||
</section>
|
||
</a></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="68b3" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq">Further Reading for Embedded
|
||
Rust</h1>
|
||
<p id="2b19" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">1️⃣ <strong class="gj gz"><em
|
||
class="ht">“</em></strong><a
|
||
href="https://rust-embedded.github.io/book/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz"><em
|
||
class="ht">The Embedded Rust Book</em></strong></a><strong class="gj gz"><em
|
||
class="ht">”</em></strong> was highly informative for embedded Rust programming on Arm Cortex M3
|
||
</p>
|
||
<p id="5798" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <em class="ht">“</em><a
|
||
href="https://os.phil-opp.com/" class="at cg gv gw gx gy"
|
||
target="_blank" rel="noopener nofollow"><strong class="gj gz"><em class="ht">Writing an OS in
|
||
Rust</em></strong></a><strong class="gj gz">” </strong>has plenty of tips for coding operating
|
||
systems in Rust</p>
|
||
<p id="d525" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <code
|
||
class="dm ln lo lp lq b"><a href="https://github.com/hashmismatch/freertos.rs" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj gz">freertos.rs</strong></a></code>
|
||
(Rust wrapper for <a href="https://www.freertos.org/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">FreeRTOS</a>) was the original
|
||
inspiration for creating a safe Rust wrapper around an embedded operating system</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="js jt ju">
|
||
<p id="634a" class="gh gi ec ht gj b gk gl gm gn go gp gq gr gs gt gu"><em class="bk">💎 </em>The
|
||
following Advanced Topic sections are for advanced developers. If you’re new to embedded
|
||
programming, you may stop here.</p>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="34b5" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq"><em class="nr">💎 </em>Advanced
|
||
Topic: Calling C from Rust and back</h1>
|
||
<p id="55a6" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">In this section we go into detail
|
||
to see how C functions and <code class="dm ln lo lp lq b">structs</code> are imported into Rust, and
|
||
how to export Rust functions to C.</p>
|
||
<blockquote class="kw">
|
||
<div id="494a" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Import C Functions into Rust: Rust ⟶ C</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="1ebd" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">For our demo Rust application, we
|
||
shall be calling the <a
|
||
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_api.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Mynewt Sensor API</a> to configure
|
||
the onboard temperature sensor to be polled every 10 seconds. After polling the sensor, Mynewt should
|
||
call a Listener Function (defined in Rust) to display the result.</p>
|
||
<p id="dfbc" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To import the Mynewt Sensor API
|
||
functions into our Rust application, we should include this code…</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/4086dff9b067959c5e337d1c164eea96.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust code to import Mynewt Sensor API. From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L35-L62"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L35-L62</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="4a5c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">How did we derive the Rust import
|
||
declarations above? Let’s look at the C declarations for the three Mynewt functions (right column) and
|
||
see how they map to the Rust import declaration (left column)…</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/b90f0bba75b16321a2fe3eb0e046bd09.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust vs C declarations for Mynewt Sensor API.
|
||
From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L35-L62"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L35-L62</a>
|
||
and <a
|
||
href="https://github.com/apache/mynewt-core/blob/master/hw/sensor/include/sensor/sensor.h#L278-L296"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/apache/mynewt-core/blob/master/hw/sensor/include/sensor/sensor.h</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<ul class="">
|
||
<li id="69c8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">#[link(name = “hw_sensor”)]</code> declares to Rust that the C functions
|
||
to be imported will be located in the compiled C library archive <code
|
||
class="dm ln lo lp lq b">hw_sensor.a</code> (which will be generated by the Mynewt build)</li>
|
||
<li id="47cf" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">i32</code> in Rust is equivalent to <code
|
||
class="dm ln lo lp lq b">int</code> in C (signed 32-bit integer)</li>
|
||
<li id="9360" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">u32</code> in Rust is equivalent to <code
|
||
class="dm ln lo lp lq b">uint32_t</code> in C (unsigned 32-bit integer)</li>
|
||
<li id="b689" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">u8</code> in Rust is equivalent to <code
|
||
class="dm ln lo lp lq b">uint8_t</code> in C (unsigned byte)</li>
|
||
<li id="835b" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">*const u8</code> in Rust is equivalent to <code
|
||
class="dm ln lo lp lq b">const uint8_t *</code> in C. We use this to pass <code
|
||
class="dm ln lo lp lq b">devname</code> because <code
|
||
class="dm ln lo lp lq b">const uint8_t *</code> has the same size as <code
|
||
class="dm ln lo lp lq b">const char *</code></li>
|
||
<li id="1d4c" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">SensorListener</code> is a <code class="dm ln lo lp lq b">struct</code>
|
||
we imported from Mynewt to pass the listener info from Rust to C (to be explained in a while)</li>
|
||
<li id="1368" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">*mut SensorListener</code> in Rust is equivalent to <code
|
||
class="dm ln lo lp lq b">struct SensorListener *</code> in C</li>
|
||
<li id="19e8" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu">Why <code
|
||
class="dm ln lo lp lq b">*mut SensorListener</code> and not <code
|
||
class="dm ln lo lp lq b">*const SensorListener</code>? Because <code
|
||
class="dm ln lo lp lq b">SensorListener</code> will be stored and updated by Mynewt.</li>
|
||
<li id="752f" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu">We define <code
|
||
class="dm ln lo lp lq b">SensorPtr</code> as follows…</li>
|
||
</ul>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/bfe4f6d64c5039bf81d1d20c9f9ad0b0.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust code to import Mynewt Sensor API Types.
|
||
From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L101-L120"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L101-L120</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<ul class="">
|
||
<li id="9b5f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">SensorPtr</code> represents a pointer to a Mynewt <code
|
||
class="dm ln lo lp lq b">sensor</code> <code class="dm ln lo lp lq b">struct</code>. Since we are
|
||
just passing the pointer through from Rust to Mynewt, without touching its contents, we declare
|
||
<code class="dm ln lo lp lq b">SensorPtr</code> as a <code class="dm ln lo lp lq b">void *</code>
|
||
type, which is <code class="dm ln lo lp lq b">*const CVoid</code> in Rust.</li>
|
||
<li id="a9fe" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">CVoid</code> is our Rust equivalent of <code
|
||
class="dm ln lo lp lq b">void</code> in C</li>
|
||
</ul>
|
||
<div class="figure hb hc hd he hf cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure hb hc hd he hf cz mt mu paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="kw">
|
||
<div id="d786" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Import C Structs into Rust: Rust ⟵📦⟶ C</p>
|
||
</div>
|
||
</blockquote>
|
||
<div class="figure lr ls lt lu lv cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/6a55995681fe88fe99639d808aa3dae1.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust code to import Mynewt SensorListener
|
||
struct. From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L63-L82"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L63-L82</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="31a0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Rust code above should be
|
||
included into our Rust application so that the <code class="dm ln lo lp lq b">SensorListener</code>
|
||
<code class="dm ln lo lp lq b">struct</code> may be passed through <code
|
||
class="dm ln lo lp lq b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor_register_listener</a>()</code>.
|
||
To understand how the Rust import declaration was derived, let’s compare the Rust import declaration
|
||
with the Mynewt declaration in C…</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/ce3b97055a6f25a2efe1c045163ac33d.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Rust vs C declarations for Mynewt
|
||
SensorListener struct. From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L63-L82"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L63-L82</a>
|
||
and <a
|
||
href="https://github.com/apache/mynewt-core/blob/master/hw/sensor/include/sensor/sensor.h#L278-L296"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/apache/mynewt-core/blob/master/hw/sensor/include/sensor/sensor.h#L278-L296</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<ul class="">
|
||
<li id="0936" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">#[repr(C)]</code> tells Rust that this <code
|
||
class="dm ln lo lp lq b">struct</code> is used by both Rust and C functions. The <code
|
||
class="dm ln lo lp lq b">struct</code> memory layout shall be fixed according to the C convention.
|
||
</li>
|
||
<li id="5656" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">#[repr(C, packed)]</code> is used for C <code
|
||
class="dm ln lo lp lq b">structs</code> that are <code class="dm ln lo lp lq b">packed</code></li>
|
||
<li id="aa74" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">SensorType</code>, <code class="dm ln lo lp lq b">SensorArg</code>, <code
|
||
class="dm ln lo lp lq b">SensorDataFunc</code> are defined in the Sensor Types Definition code
|
||
above</li>
|
||
<li id="f67a" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">SensorDataFunc</code> is a pointer to a callback function in Rust that
|
||
Mynewt will call from a C function. This is explained below.</li>
|
||
<li id="79e3" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu ns nt nu"><code
|
||
class="dm ln lo lp lq b">sl_next</code> is defined as <code class="dm ln lo lp lq b">u32</code>
|
||
(32-bit unsigned integer) because we should initialise the field to <code
|
||
class="dm ln lo lp lq b">0</code> in our Rust code. <code class="dm ln lo lp lq b">sl_next</code>
|
||
is updated by Mynewt to store the pointer to the next <code
|
||
class="dm ln lo lp lq b">SensorListener</code> in the linked list</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure hb hc hd he hf cz mt mu paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="kw">
|
||
<div id="1864" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Export Rust Functions to C (Callback): Rust ⟵ C</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="a1cd" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">We have seen how C functions and
|
||
structs may be imported into Rust. Now let’s see how Rust functions may be called from C.</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/4b0728052ee94db3c0b83188fb1ba382.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs#L20-L56"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs#L20-L56</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="12f8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Recall that <code
|
||
class="dm ln lo lp lq b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">sensor_register_listener</a>()</code>
|
||
registers a Listener Function (defined in Rust) that will be called by Mynewt when the temperature
|
||
sensor has been polled. <code class="dm ln lo lp lq b">sensor_register_listener()</code> accepts a
|
||
<code class="dm ln lo lp lq b">SensorListener</code> <code class="dm ln lo lp lq b">struct</code>
|
||
(named <code class="dm ln lo lp lq b">LISTENER</code> here) as a parameter. The <code
|
||
class="dm ln lo lp lq b">SensorListener</code> <code class="dm ln lo lp lq b">struct</code> includes
|
||
<code class="dm ln lo lp lq b">sl_func</code>, the pointer to the Listener Function.</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/b5aeea3ea4d702d9200a7919f4c9e534.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs#L41-L48"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs#L41-L48</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="d4de" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here we pass the Rust function
|
||
<code class="dm ln lo lp lq b">read_temperature()</code> as the Listener Function.</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/7bd0b8a844fa12d5860e4585d2566ed5.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em><a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs#L62-L108"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/listen_sensor.rs#L62-L108</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="7cc4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ln lo lp lq b">read_temperature()</code> is declared as <code
|
||
class="dm ln lo lp lq b">extern</code> so that it may be called from C as a callback function
|
||
(instead of calling by function name). Note that <code
|
||
class="dm ln lo lp lq b">read_temperature()</code> has the same function signature as <code
|
||
class="dm ln lo lp lq b">sl_func</code> (which has type <code
|
||
class="dm ln lo lp lq b">SensorDataFunc</code>)…</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/d2494d75118353e9910d629f8467ade8.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L63-L109"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/sensor.rs#L63-L109</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hw hx hy hz ia ib ag ic ah id aj ak">
|
||
<div class="figure hb hc hd he hf cz mt mu paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="kw">
|
||
<div id="c159" class="kx ky kz bk ed b la lb lc ld le lf gu">
|
||
<p class="ed b lg lh bo">Export Rust Functions to C (Call By Name): Rust ⟵ C</p>
|
||
</div>
|
||
</blockquote>
|
||
<p id="dc5c" class="gh gi ec bk gj b gk li gm lj go lk gq ll gs lm gu">Previously we have seen how C may
|
||
call a Rust function <em class="ht">via callback</em> (i.e. the Rust function is passed to C as a
|
||
pointer). What if our C function wishes to call a Rust function <em class="ht">by its function
|
||
name?</em></p>
|
||
<p id="d304" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Normally the Rust compiler
|
||
converts Rust function names into a “mangled” format that includes the function signature. So the
|
||
<code class="dm ln lo lp lq b">read_temperature()</code> function would be compiled and renamed as:
|
||
<code class="dm ln lo lp lq b">_ZN5mylib13listen_sensor16read_temperature17h318673dbfba97d4bE()</code>
|
||
</p>
|
||
<p id="6b12" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But if we are calling <code
|
||
class="dm ln lo lp lq b">read_temperature()</code> from C, this becomes a problem because the
|
||
function name has changed. To prevent the mangling of the Rust function name, use the <code
|
||
class="dm ln lo lp lq b">#[no_mangle]</code> directive like this:</p>
|
||
<div class="figure hb hc hd he hf cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/e8cce792e9259b7e680619a06fe6040a.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/lib.rs#L21-L48"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/rust/src/lib.rs#L21-L48</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="1dfa" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">So in the above code, the
|
||
function <code class="dm ln lo lp lq b">main()</code> will not be renamed by the Rust compiler. The
|
||
<code class="dm ln lo lp lq b">pub extern “C”</code> directive tells the Rust compiler to export the
|
||
Rust function <code class="dm ln lo lp lq b">main()</code> to C functions.</p>
|
||
<p id="66c1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">From a C function, we may now
|
||
call the function by its Rust name, <code class="dm ln lo lp lq b">main()</code>. In fact that’s how
|
||
Mynewt starts our Rust application.</p>
|
||
<p id="d404" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This interoperability of Rust and
|
||
C is known as the <strong class="gj gz">Foreign Function Interface</strong>. <a
|
||
href="https://doc.rust-lang.org/1.6.0/book/ffi.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Read the details here</a>.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="jv dy jw jx jy dv jz ka kb kc kd" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="074d" class="ke kf ec bk bj jg kg kh ki kj kk kl km kn ko kp kq"><em class="nr">💎 </em>Advanced
|
||
Topic: Enhancements</h1>
|
||
<p id="c64c" class="gh gi ec bk gj b gk kr gm ks go kt gq ku gs kv gu">Although we have done a lot in
|
||
this article, we haven’t provided a <strong class="gj gz">comprehensive and maintainable
|
||
environment</strong> in Mynewt for hosting all kinds of Embedded Rust applications.</p>
|
||
<p id="d143" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here are my suggestions for
|
||
<strong class="gj gz">improving the integration</strong> of Rust with Mynewt. <em class="ht">If you’re
|
||
keen to work on the integration of Rust with Mynewt, lemme know!</em></p>
|
||
<ol class="">
|
||
<li id="68eb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu oa nt nu">Rust folders should
|
||
<strong class="gj gz">follow the Mynewt folder structure</strong>:<br />Move Rust source files from
|
||
<code class="dm ln lo lp lq b">src</code> to <code
|
||
class="dm ln lo lp lq b">apps/my_sensor_app/src</code><br />Generate compiled Rust object files in
|
||
<code class="dm ln lo lp lq b">bin</code> instead of <code class="dm ln lo lp lq b">target</code>
|
||
</li>
|
||
<li id="08e7" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu"><strong
|
||
class="gj gz">Auto-generate the Rust code for importing Mynewt C functions and </strong><code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">structs</strong></code>. <code
|
||
class="dm ln lo lp lq b">bindgen</code> is a tool that we could use to generate the Rust import
|
||
declarations by feeding in the Mynewt header files. <a class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener"
|
||
href="https://lupyuen.github.io/articles/safer-simpler-embedded-rust-with-apache-mynewt-on-stm32-blue-pill">Already
|
||
done here</a>.</li>
|
||
<li id="fd1b" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu">Create <strong
|
||
class="gj gz">safe Rust wrappers for the complete Mynewt API</strong>. We may need lots of
|
||
thinking to create a safe Rust API for Mynewt that’s easy to use and error-proof. <a
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/safer-simpler-embedded-rust-with-apache-mynewt-on-stm32-blue-pill">Already
|
||
done here</a>.</li>
|
||
<li id="36ea" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu">Rust wrappers for
|
||
Mynewt should return <code
|
||
class="dm ln lo lp lq b"><strong class="gj gz">Result</strong></code><strong class="gj gz"> type
|
||
instead of integers</strong> (thanks to <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/issues/3"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Marcel Hellwig</a>). <a
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/safer-simpler-embedded-rust-with-apache-mynewt-on-stm32-blue-pill">Already
|
||
done here</a>.</li>
|
||
<li id="b578" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu"><strong
|
||
class="gj gz">CoAP (JSON and CBOR) API</strong> for Rust, similar to the network-agnostic <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/rust/libs/sensor_network"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Sensor Network API</a>. <a
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/safer-simpler-embedded-rust-with-apache-mynewt-on-stm32-blue-pill">Already
|
||
done here</a>.</li>
|
||
<li id="7cda" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu">Allow Mynewt <strong
|
||
class="gj gz">drivers and libraries to be created with Rust</strong></li>
|
||
<li id="0a9a" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu"><strong
|
||
class="gj gz">Support other microcontroller platforms</strong> besides Blue Pill</li>
|
||
<li id="9fcd" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu">Support <strong
|
||
class="gj gz">text formatting and heap allocator</strong> in Rust. While keeping RAM and ROM usage
|
||
low.</li>
|
||
<li id="e9c8" class="gh gi ec bk gj b gk nv gm nw go nx gq ny gs nz gu oa nt nu">Keep <strong
|
||
class="gj gz">monitoring for RAM and ROM bloat</strong> as we implement enhancements. For example,
|
||
the ROM size dropped from 73 KB to 55 KB after removing the <code
|
||
class="dm ln lo lp lq b">unwrap() / panic()</code> error checking. Check the memory map <a
|
||
href="https://docs.google.com/spreadsheets/d/1yep-QaAoaxrBz8tpYZ2TMo1xWNDaKCaFCGS-kON1Rt0/edit#gid=381366828&fvid=1643056349"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">before</a> and <a
|
||
href="https://docs.google.com/spreadsheets/d/1tWbH8MMZE5_2NsaWs1qNHDC6V8iR8Hx-Le95gHS69fo/edit#gid=381366828&fvid=1643056349"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">after</a>. <em
|
||
class="ht">(</em><a class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/stm32-blue-pill-analyse-and-optimise-your-ram-and-rom"><em
|
||
class="ht">Learn more about memory maps</em></a><em class="ht">)</em></li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure hb hc hd he hf cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/e17.png" /></p>
|
||
|
||
<figcaption><p><em>ROM usage before and after removing <code
|
||
class="dm ln lo lp lq b">unwrap() / panic()</code> error checking. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1yep-QaAoaxrBz8tpYZ2TMo1xWNDaKCaFCGS-kON1Rt0/edit#gid=381366828"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1yep-QaAoaxrBz8tpYZ2TMo1xWNDaKCaFCGS-kON1Rt0/edit#gid=381366828</a>
|
||
and <a
|
||
href="https://docs.google.com/spreadsheets/d/1tWbH8MMZE5_2NsaWs1qNHDC6V8iR8Hx-Le95gHS69fo/edit#gid=381366828&fvid=1643056349"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1tWbH8MMZE5_2NsaWs1qNHDC6V8iR8Hx-Le95gHS69fo/edit#gid=381366828&fvid=1643056349</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</div>
|
||
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/sponsors/lupyuen">Sponsor me a coffee</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io">Check out my articles</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/rss.xml">RSS Feed</a></p>
|
||
</li>
|
||
</ul>
|
||
|
||
</body>
|
||
|
||
</html>
|
||
<!--
|
||
FILE ARCHIVED ON 19:42:25 Dec 04, 2019 AND RETRIEVED FROM THE
|
||
INTERNET ARCHIVE ON 01:29:47 Feb 23, 2021.
|
||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
|
||
|
||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
|
||
SECTION 108(a)(3)).
|
||
-->
|
||
<!--
|
||
playback timings (ms):
|
||
esindex: 0.013
|
||
captures_list: 166.055
|
||
load_resource: 90.608
|
||
RedisCDXSource: 1.398
|
||
LoadShardBlock: 129.449 (3)
|
||
exclusion.robots: 0.41
|
||
PetaboxLoader3.datanode: 135.395 (4)
|
||
exclusion.robots.policy: 0.394
|
||
CDXLines.iter: 30.061 (3)
|
||
PetaboxLoader3.resolve: 48.522
|
||
--> |