lupyuen.org/articles/stm32-blue-pill-shrink-your-math-libraries-with-qfplib.html

782 lines
54 KiB
HTML
Raw Permalink Normal View History

2021-02-23 09:51:56 +08:00
<!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" />
2024-12-30 11:07:24 +08:00
<link rel="canonical" href="https://lupyuen.org/articles/stm32-blue-pill-shrink-your-math-libraries-with-qfplib.html" />
2021-02-23 09:51:56 +08:00
<!-- End Wayback Rewrite JS Include -->
<title data-rh="true">STM32 Blue Pill Shrink your math libraries with Qfplib</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-01-30T09:53:36.711Z" />
<meta data-rh="true" name="title" content="STM32 Blue Pill Shrink your math libraries with Qfplib" />
<meta data-rh="true" property="og:title" content="STM32 Blue Pill Shrink your math libraries with Qfplib" />
<meta data-rh="true" property="twitter:title" content="STM32 Blue Pill Shrink your math libraries with Qfplib" />
<meta data-rh="true" name="description"
content="Floating-point math libraries can bloat your Blue Pill code. Heres one way to fix that" />
<meta data-rh="true" property="og:description"
content="Floating-point math libraries can bloat your Blue Pill code. Heres one way to fix that" />
<meta data-rh="true" property="twitter:description"
content="Floating-point math libraries can bloat your Blue Pill code. Heres one way to fix that" />
<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="9 min read" />
2021-02-26 13:24:17 +08:00
<meta property="og:image"
content="https://lupyuen.github.io/images/legacy2/m1.png">
2021-02-23 13:03:17 +08:00
<!-- 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">
2021-02-25 08:40:21 +08:00
2021-02-23 13:03:17 +08:00
<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 -->
2021-02-23 09:51:56 +08:00
</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">
2021-02-25 21:05:13 +08:00
<div class="figure da cz ak paragraph-image">
2021-02-24 09:03:17 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m1.png" /></p>
2021-02-25 16:11:14 +08:00
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
</div>
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<div>
<div id="457c" class="dq dr ds bk dt b du dv dw dx dy dz ea">
<h1 class="dt b du eb ds">STM32 Blue Pill Shrink your math libraries with Qfplib</h1>
</div>
<div class="ec">
<div class="n ed ee ef eg">
<div class="o n">
<div><a rel="noopener"
2021-02-26 07:32:12 +08:00
href="https://lupyuen.github.io">
2021-02-23 09:51:56 +08:00
<div class="di eh ei">
2021-02-25 22:31:47 +08:00
<div class="bs n ej o p cp ek el em en eo ct"></div>
2021-02-23 09:51:56 +08:00
</div>
</a></div>
<div class="eq ak r">
<div class="n">
<div style="flex:1"><span class="bj b bk bl bm bn r ds q">
<div class="er n o es"><span class="bj et eu bl de ev ew ex ey ez ds"><a
class="at au av aw ax ay az ba bb bc fa bf bg bh bi" rel="noopener"
2021-02-26 07:32:12 +08:00
href="https://lupyuen.github.io">Lup
2021-02-23 09:51:56 +08:00
Yuen Lee 李立源</a></span>
2021-02-25 16:37:54 +08:00
2021-02-23 09:51:56 +08:00
</div>
</span></div>
</div><span class="bj b bk bl bm bn r bo bp"><span class="bj et eu bl de ev ew ex ey ez bo">
<div><a class="at au av aw ax ay az ba bb bc fa bf bg bh bi" rel="noopener"
2021-02-25 22:10:34 +08:00
href="https://lupyuen.github.io/articles/stm32-blue-pill-shrink-your-math-libraries-with-qfplib">
30 Jan 2019</a> <!-- -->·
2021-02-23 09:51:56 +08:00
<!-- -->
<!-- -->9
<!-- --> min read
</div>
</span></span>
</div>
</div>
</div>
</div>
</div>
<p id="7318" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Check out this magic trick… Why
does <a
2021-02-23 17:24:18 +08:00
href="http://wiki.stm32duino.com/index.php?title=Blue_Pill"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">Blue Pill</a> think that <strong
class="gb gr">123</strong> times <strong class="gb gr">456</strong> is <strong
class="gb gr">123,456</strong> ???!!! <a
2021-02-23 17:24:18 +08:00
href="https://github.com/lupyuen/stm32bluepill-math-hack"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">Heres the full source code</a>.
</p>
</div>
</div>
<div class="cz ak">
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz">
2021-02-23 09:51:56 +08:00
<div class="dh r di">
<div class="gx r"><iframe
2021-02-23 10:09:08 +08:00
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F3AedU60qGFI%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D3AedU60qGFI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F3AedU60qGFI%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
2021-09-28 08:18:14 +08:00
allowfullscreen="" frameborder="0" height="300" width="400" title="STM32 Blue Pill Math Hack"
2021-02-23 09:51:56 +08:00
class="cp t u dd ak" scrolling="auto"></iframe></div>
</div>
2021-02-25 21:00:07 +08:00
<figcaption><p><em>Blue Pill thinks that 123 times 456 is 123,456
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
</div>
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<p id="c4ff" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">This article explains how we
hacked Blue Pill to create this interesting behaviour, and how we may exploit this hack to cut down
the size of our math libraries…</p>
<ol class="">
<li id="2b57" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm hd he hf">What are <strong
class="gb gr">Math Libraries</strong>? How does Blue Pill perform math computations?</li>
<li id="e9d5" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm hd he hf"><strong
class="gb gr">Qfplib</strong> the tiny math library</li>
<li id="9fb2" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm hd he hf"><strong
class="gb gr">Single vs Double-Precision</strong> numbers. Do we really need Double-Precision?
</li>
<li id="c835" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm hd he hf">Filling in the
missing math functions with <code
class="dj hl hm hn ho b"><strong class="gb gr">nano-float</strong></code></li>
<li id="7992" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm hd he hf"><strong
class="gb gr">Testing</strong> Qfplib and nano-float</li>
<li id="1735" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm hd he hf"><strong
class="gb gr">My experience</strong> with Qfplib and nano-float</li>
</ol>
<p id="5c62" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><strong class="gb gr"><em
class="hp">This article covers experimental topics that have not been tested in production
systems, so be very careful if you decide to use any tips from this article.</em></strong></p>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<h1 id="4b56" class="hz ia ds bk bj ib ic id ie if ig ih ii ij ik il im">What are Math Libraries? Why so
huge?</h1>
<p id="def5" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm">If you have used math functions
like <code class="dj hl hm hn ho b">sin(), log(), floor(), ...</code> then you would have used the
<code class="dj hl hm hn ho b"><strong class="gb gr">libm.a</strong></code><strong class="gb gr">
Standard Math Library for C</strong>. Its a bunch of common math functions that we may call from C
and C++ programs running on Blue Pill and virtually any microcontroller and any device.</p>
<p id="0d38" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">But theres a catch… The math
functions will perform better on some microcontrollers and devices — those that support <strong
class="gb gr">hardware floating-point operations in their processors</strong>.</p>
<p id="5701" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Unfortunately <strong
class="gb gr">Blue Pill is not in that list.</strong> The math libraries are implemented in
software, not hardware. So a single call to <code class="dj hl hm hn ho b">sin()</code> could actually
keep the Blue Pill busy for a (short) while because of the <a
2021-02-23 17:24:18 +08:00
href="https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ieee754/dbl-64/s_sin.c;h=7584afcd2b016fd94f8452d30f5d3542a831b5b3;hb=refs/heads/master"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">complicated library code</a>. And
the complicated math code also causes Blue Pill programs to bloat beyond their ROM limit (64 KB).</p>
<p id="f95a" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Is there a better way to do math
on Blue Pill? The secret lies in the Magic Trick…</p>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz">
2021-02-23 10:09:08 +08:00
2021-02-23 10:55:05 +08:00
<p><script src="https://gist.github.com/lupyuen/757429ba987bdaafc0f62f31757698a1.js"></script></p>
2021-02-23 10:09:08 +08:00
2021-02-25 21:00:07 +08:00
<figcaption><p><em>From <a
2021-02-23 17:24:18 +08:00
href="https://github.com/lupyuen/stm32bluepill-math-hack/blob/master/src/main.c"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-math-hack/blob/master/src/main.c</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
<h1 id="b691" class="hz ia ds bk bj ib ic it ie iu ig iv ii iw ik ix im">Magic Trick Revealed</h1>
<p id="6695" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm">Remember the above code from the
Magic Trick… Why does Blue Pill think that 123 times 456 is 123,456? Lets look at the <a
2021-02-23 17:24:18 +08:00
href="https://github.com/lupyuen/stm32bluepill-math-hack/blob/master/firmware.dump"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">Assembly Code</a> (check <a
class="at cg gn go gp gq" target="_blank" rel="noopener"
2021-02-25 17:57:35 +08:00
href="https://lupyuen.github.io/articles/stm32-blue-pill-analyse-and-optimise-your-ram-and-rom">my
2021-02-23 09:51:56 +08:00
previous article</a> for the “Disassemble” task)…</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="iy iz ja jb jc jd ag je ah jf aj ak">
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz jh ji paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m2.png" /></p>
2021-02-25 16:11:14 +08:00
2021-02-25 21:00:07 +08:00
<figcaption><p><em>Assembly Code for the magic trick. From <a
2021-02-23 17:24:18 +08:00
href="https://github.com/lupyuen/stm32bluepill-math-hack/blob/master/firmware.dump"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-math-hack/blob/master/firmware.dump</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<p id="03df" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Something suspicious is happening
here… the line</p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="9af6" class="jq ia ds bk ho b eu jr js r jt">r = x * y</span></pre>
<p id="bf8a" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">has actually been compiled into a
function call that looks like…</p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="1620" class="jq ia ds bk ho b eu jr js r jt">r = __wrap___aeabi_dmul(x, y)</span></pre>
<p id="498b" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Multiplication of numbers looks
<em class="hp">simple and harmless</em> when we write it as <code
class="dj hl hm hn ho b"><strong class="gb gr">x * y</strong></code>. But remember that <code
class="dj hl hm hn ho b">x</code> and <code class="dj hl hm hn ho b">y</code> are floating-point
numbers. And Blue Pill cant compute floating-point numbers in hardware. <strong class="gb gr">So Blue
Pill needs to call a math library function </strong><code
class="dj hl hm hn ho b"><strong class="gb gr">__wrap___aeabi_dmul</strong></code><strong
class="gb gr"> to compute </strong><code
class="dj hl hm hn ho b"><strong class="gb gr">x * y !</strong></code></p>
<p id="bbfb" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><em class="hp">It looks more
sinister now…</em></p>
<p id="caeb" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Remember this function that
appears at the end of the magic trick?</p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="87d8" class="jq ia ds bk ho b eu jr js r jt">double __wrap___aeabi_dmul(double x, double y) { <br/> return 123456; <br/>}</span></pre>
<p id="da9c" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Thats where the magic happens —
<strong class="gb gr">it returns </strong><code
class="dj hl hm hn ho b"><strong class="gb gr">123456</strong></code><strong class="gb gr"> for any
multiplication of </strong><code
class="dj hl hm hn ho b"><strong class="gb gr">doubles</strong></code> in the program. We have
intercepted the multiplication operation to return a hacked result.</p>
<p id="cf7a" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><code
class="dj hl hm hn ho b">__wrap___aeabi_dmul</code> is typically a function with lots of computation
code inside… <strong class="gb gr">1 KB of compiled code</strong>. So our code size will bloat
significantly once we start using floating-point computation on Blue Pill.</p>
<p id="e8c5" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Now what if we do this…</p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="f5c4" class="jq ia ds bk ho b eu jr js r jt">double __wrap___aeabi_dmul(double x, double y) { <br/> return qfp_fmul(x, y); <br/>}</span></pre>
<p id="34c5" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><strong class="gb gr">What if we
could find a tiny function </strong><code
class="dj hl hm hn ho b"><strong class="gb gr">qfp_fmul</strong></code><strong class="gb gr"> that
multiplies floating-point numbers without bloating the code size?</strong> That would be perfect for
Blue Pill! <code class="dj hl hm hn ho b">qfp_fmul</code> actually exists and its part of the <strong
class="gb gr">Qfplib</strong> library, coming up next…</p>
<blockquote class="ju jv jw">
<p id="0df5" class="fz ga ds hp gb b gc gd ge gf gg gh gi gj gk gl gm">💎 About the <code
class="dj hl hm hn ho b">wrap</code>: The <code class="dj hl hm hn ho b">wrap</code> prefix was
inserted because we used this linker option in <a
2021-02-23 17:24:18 +08:00
href="https://github.com/lupyuen/stm32bluepill-math-hack/blob/master/platformio.ini"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">platformio.ini</a>:<code
class="dj hl hm hn ho b"> -Wl,-wrap,__aeabi_dmul</code>. Without <code
class="dj hl hm hn ho b">wrap</code>, the function name is actually <code
class="dj hl hm hn ho b"><em class="bk">__aeabi_dmul</em></code><em class="bk">. </em>By using
<code class="dj hl hm hn ho b">wrap</code> we can easily identify the functions that we have
intercepted. <a
2021-02-23 17:24:18 +08:00
href="http://infocenter.arm.com/help/topic/com.arm.doc.ihi0043d/IHI0043D_rtabi.pdf"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">Check this doc for more info on
AEABI functions</a>.</p>
</blockquote>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<div class="gs gt gu gv gw jx"><a
2021-02-23 17:24:18 +08:00
href="https://www.quinapalus.com/qfplib.html?source=post_page-----55093aab163a----------------------"
2021-02-23 09:51:56 +08:00
rel="noopener nofollow">
<section class="ka cl cm ak ce n ar kb kc kd ke kf kg kh ki kj kk kl km kn ko kp">
<div class="kq n co p kr ks">
<h2 class="bj ib kt bl ds">
<div class="de jy ew ex jz ez">Qfplib: an ARM Cortex-M0 floating-point library in 1 kbyte
</div>
</h2>
</div>
<div class="kw r">
<div class="kx r ky kz la kw lb lc ld"></div>
</div>
</section>
</a></div>
<h1 id="90cc" class="hz ia ds bk bj ib ic it ie iu ig iv ii iw ik ix im">Qfplib the tiny floating-point
library</h1>
<p id="2a56" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm"><a
2021-02-23 17:24:18 +08:00
href="https://www.quinapalus.com/qfplib.html"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">Qfplib</a> is a floating-point
math library by Dr Mark Owen thats incredibly small. In a mere <strong class="gb gr">1,224
bytes</strong> we get Assembly Code functions (specific to Arm Cortex-M0 and above) that compute…
</p>
<ul class="">
<li id="9f39" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm le he hf"><code
class="dj hl hm hn ho b">qfp_fadd, qfp_fsub, qfp_fmul, qfp_fdiv_fast</code>: Floating-point
addition, subtraction, multiplication, division</li>
<li id="caaf" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm le he hf"><code
class="dj hl hm hn ho b">qfp_fsin, qfp_fcos, qfp_ftan, qfp_fatan2</code>: sine, cosine, tangent,
inverse tangent</li>
<li id="c763" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm le he hf"><code
class="dj hl hm hn ho b">qfp_fexp, qfp_fln</code>: Natural exponential, logarithm</li>
<li id="ff17" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm le he hf"><code
class="dj hl hm hn ho b">qfp_fsqrt_fast, qfp_fcmp</code>: Square root, comparison of floats</li>
</ul>
<p id="d8a8" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Plus conversion functions for
integers, fixed-point and floating-point numbers. What a gem!</p>
<p id="cf8d" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">With Qfplib we may now intercept
any floating-point operation (using the <code class="dj hl hm hn ho b">__wrap___aeabi_dmul</code>
method above) and <strong class="gb gr">substitute a smaller, optimised version</strong> of the
computation code.</p>
<p id="db22" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Be careful: There are <strong
class="gb gr">limitations in the Qfplib functions</strong>, <a
2021-02-23 17:24:18 +08:00
href="https://www.quinapalus.com/qfplib.html"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">as described here</a>. And Qfplib
only handles <strong class="gb gr">single-precision math, not double-precision</strong>. More about
this…</p>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<h1 id="5ed2" class="hz ia ds bk bj ib ic id ie if ig ih ii ij ik il im">Single vs Double-Precision
Floating-Point Numbers</h1>
<p id="4a0f" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm">You should have seen
single-precision (<code class="dj hl hm hn ho b">float</code>) and double-precision (<code
class="dj hl hm hn ho b">double</code>) numbers in C programs…</p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="0b44" class="jq ia ds bk ho b eu jr js r jt">float x = 123.456; // Single precision (32 bits)<br/>double y = 123.456789012345; // Double precision (64 bits)</span></pre>
<p id="8f4c" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Double-precision numbers are more
precise in representing floating-point numbers because they have twice the number of bits (<strong
class="gb gr">64 bits</strong>) compared with single-precision numbers (<strong class="gb gr">32
bits</strong>).</p>
<p id="89d1" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">To be more specific…
single-precision numbers are stored in the <a
2021-02-23 17:24:18 +08:00
href="https://en.wikipedia.org/wiki/Single-precision_floating-point_format"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">IEEE 754 Single-Precision
format</a> which gives us <strong class="gb gr">6 significant decimal digits</strong>. So this <code
class="dj hl hm hn ho b">float</code> value is OK because its only 6 decimal digits…</p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="8454" class="jq ia ds bk ho b eu jr js r jt">float x = 123.456; // OK for Single Precision</span></pre>
<p id="86c1" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">But we may lose the seventh digit
in this <code class="dj hl hm hn ho b">float</code> value because 32 bits cant fully accommodate 7
decimal digits…</p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="62a8" class="jq ia ds bk ho b eu jr js r jt">float y = 123.4567; // Last digit may be truncated for Single Precision</span></pre>
<p id="cbf7" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">And Blue Pill may think that
<code class="dj hl hm hn ho b">x</code> has the same value as <code class="dj hl hm hn ho b">y</code>.
We wouldnt use <code class="dj hl hm hn ho b">float</code> to count 10 million dollars (7 decimal
digits or more).</p>
<p id="22ca" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">With double-precision numbers
(stored as <a
2021-02-23 17:24:18 +08:00
href="https://en.wikipedia.org/wiki/Double-precision_floating-point_format"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">IEEE 754 Double-Precision
format</a>) we have room for <strong class="gb gr">15 significant decimal digits</strong></p>
<pre
class="gs gt gu gv gw jn jo jp"><span id="873e" class="jq ia ds bk ho b eu jr js r jt">double y = 123.456789012345; // OK for Double Precision</span></pre>
<p id="fd0a" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Double precision is indeed more
precise than single precision. BUT…</p>
<ol class="">
<li id="5194" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm hd he hf"><code
class="dj hl hm hn ho b">doubles</code> take up <strong class="gb gr">twice the storage</strong>
</li>
<li id="c915" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm hd he hf"><code
class="dj hl hm hn ho b">doubles</code> also require <strong class="gb gr">more processor
time</strong> to compute</li>
</ol>
<p id="eb7a" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">This causes problems for
constrained microcontrollers like Blue Pill. Also if we use common math functions like <code
class="dj hl hm hn ho b">sin(), log(), floor()</code>, … we will actually introduce <code
class="dj hl hm hn ho b">doubles</code> into our code because the common math functions are declared
as <code class="dj hl hm hn ho b">double</code>. (The single-precision equivalent functions are
available, but we need to consciously select them as <code
class="dj hl hm hn ho b">sinf(), logf(), floorf()</code>, …)</p>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<h1 id="51e0" class="hz ia ds bk bj ib ic id ie if ig ih ii ij ik il im">Do we really need Double
Precision numbers?</h1>
<p id="7b5a" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm">I teach IoT. When my students
measure ambient temperature with a long string of digits like 28.12345, Im pretty sure theyre not
doing it right.</p>
<p id="f724" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Sensors are inherently noisy so I
wont trust them to produce such precise double-precision numbers. Instead I would use a Time Series
Database to <strong class="gb gr">aggregate sensor values (single-precision) over time and compute an
aggregated sensor value</strong> (say, moving average for the past minute) thats more resistant to
sensor noise.</p>
<p id="4213" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">If youre doing Scientific
Computing, then <code class="dj hl hm hn ho b">doubles</code> are for you. Then again you probably
wont be using a lower-class microcontroller like Blue Pill. Its my hunch that most Blue Pill
programmers will be perfectly happy with <code class="dj hl hm hn ho b">floats</code> instead of <code
class="dj hl hm hn ho b">doubles</code> (though I have no proof).</p>
<p id="d650" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Always exercise caution when
using <code class="dj hl hm hn ho b">floats</code> instead of <code
class="dj hl hm hn ho b">doubles</code>. Theres a possibility that some <strong
class="gb gr">intermediate computation will overflow the 6-digit limitation of </strong><code
class="dj hl hm hn ho b"><strong class="gb gr">floats,</strong></code> l<a
2021-02-23 17:24:18 +08:00
href="https://github.com/adafruit/Adafruit_BME280_Library/blob/master/Adafruit_BME280.cpp#L591"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">ike this computation</a>. GPS
coordinates (latitude, longitude) may require <code class="dj hl hm hn ho b">doubles</code> as well.
</p>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz cl cm paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m3.png" /></p>
2021-02-25 16:11:14 +08:00
2021-02-25 21:00:07 +08:00
<figcaption><p><em>nano-float function derived from Qfplib and
2021-02-23 09:51:56 +08:00
the unit test cases below. From <a
2021-02-23 17:24:18 +08:00
href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L555-L585"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L555-L585</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
<h1 id="d9db" class="hz ia ds bk bj ib ic it ie iu ig iv ii iw ik ix im">Complete Math Library:
nano-float</h1>
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz do li cd lj lk ll lm ln ba lo lp lq lr ls lt paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m4.png" /></p>
2021-02-25 16:11:14 +08:00
2021-02-25 21:00:07 +08:00
<figcaption><p><em>Functions provided by qfplib</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
<p id="31a6" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Qfplib provides the basic
float-point math functions. Many other math functions are missing: <code
class="dj hl hm hn ho b">sinh</code>, <code class="dj hl hm hn ho b">asinh</code>, … <strong
class="gb gr">Can we synthesise the other math functions</strong>?</p>
<p id="eff7" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Yes we can! And heres the proof…
</p>
<p id="f29b" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><code
class="dj hl hm hn ho b">https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c</code>
</p>
<p id="2dd9" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><code
class="dj hl hm hn ho b"><strong class="gb gr">nano-float</strong></code> is a thin layer of code I
wrote (not 100% tested) that fills in the remaining math functions by calling Qfplib. <code
class="dj hl hm hn ho b">nano-float</code> is a drop-in replacement for the standard math library,
so the function signatures for the math functions are the same… just link your program with <code
class="dj hl hm hn ho b">nano-float</code> instead of the default math library, no recompilation
needed.</p>
<p id="3a62" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">This looks like a math textbook
exercise but lets derive the missing functions based on Qfplib…</p>
<p id="bed3" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">1<code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L373-L408" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">log2</a></code><a
href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L373-L408"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow"> and </a><code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L373-L408" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">log10</a></code>
2021-02-23 09:51:56 +08:00
were derived from Qfplibs <code class="dj hl hm hn ho b">qfp_fln</code> (natural logarithm function)
because…</p>
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz cl cm paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m5.png" /></p>
2021-02-25 21:00:07 +08:00
<figcaption><p><em><a
2021-02-23 17:24:18 +08:00
href="https://en.wikipedia.org/wiki/Logarithm"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
2021-02-25 21:00:07 +08:00
rel="noopener nofollow">https://en.wikipedia.org/wiki/Logarithm</a></em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
<p id="947f" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">2<code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L555-L629" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">asin</a></code><a
href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L555-L629"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow"> and </a><code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L555-L629" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">acos</a></code>
2021-02-23 09:51:56 +08:00
(inverse sine / cosine) were derived from Qfplibs <code
class="dj hl hm hn ho b">qfp_fsqrt_fast</code> (square root) and <code
class="dj hl hm hn ho b">qfp_fatan2</code> (inverse tangent) because…</p>
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz cl cm paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m6.png" /></p>
2021-02-25 16:11:14 +08:00
2021-02-25 21:00:07 +08:00
<figcaption><p><em><a
2021-02-23 17:24:18 +08:00
href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://en.wikipedia.org/wiki/Inverse_trigonometric_functions</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
<p id="8a59" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">3<code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L631-L717" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">sinh</a></code><a
href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L631-L717"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">, </a><code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L631-L717" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">cosh</a></code><a
href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L631-L717"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow"> and </a><code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L631-L717" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">tanh</a></code>
2021-02-23 09:51:56 +08:00
(hyperbolic sine / cosine / tangent) were derived from Qfplibs <code
class="dj hl hm hn ho b">qfp_fexp</code> (natural exponential) because…</p>
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz cl cm paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m7.png" /></p>
2021-02-25 16:11:14 +08:00
2021-02-25 21:00:07 +08:00
<figcaption><p><em><a
2021-02-23 17:24:18 +08:00
href="https://en.wikipedia.org/wiki/Hyperbolic_function"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
2021-02-25 21:00:07 +08:00
rel="noopener nofollow">https://en.wikipedia.org/wiki/Hyperbolic_function</a></em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
<p id="a3f7" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">4<code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L719-L819" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">asinh</a></code><a
href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L719-L819"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">, </a><code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L719-L819" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">acosh</a></code><a
href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L719-L819"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow"> and </a><code
2021-02-23 17:24:18 +08:00
class="dj hl hm hn ho b"><a href="https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/src/functions.c#L719-L819" class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">atanh</a></code>
2021-02-23 09:51:56 +08:00
(inverse hyperbolic sine / cosine / tangent) were derived from <code
class="dj hl hm hn ho b">qfplibs</code> <code class="dj hl hm hn ho b">qfp_fln</code> (natural
logarithm) and <code class="dj hl hm hn ho b">qfp_fsqrt_fast</code> (square root) because…</p>
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz cl cm paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m8.png" /></p>
2021-02-25 21:00:07 +08:00
<figcaption><p><em><a
2021-02-23 17:24:18 +08:00
href="https://en.wikipedia.org/wiki/Inverse_hyperbolic_functions"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://en.wikipedia.org/wiki/Inverse_hyperbolic_functions</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
<p id="1b50" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">So you can see that its indeed
possible for <code class="dj hl hm hn ho b">nano-float</code> to fill in the missing math functions by
simply calling Qfplib!</p>
<p id="c6f6" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><strong class="gb gr">But watch
out for Boundary Conditions</strong> — the code in <code class="dj hl hm hn ho b">nano-float</code>
may not cover all of the special cases like <code
class="dj hl hm hn ho b">0, +infinity, -infinity, NaN</code> (not a number), …</p>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="cz ak">
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz ak paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m9.png" /></p>
2021-02-25 21:00:07 +08:00
<figcaption><p><em>nano-float unit tests automatically extracted
2021-02-23 09:51:56 +08:00
from the nano-float source code. From <a
2021-02-23 17:24:18 +08:00
href="https://docs.google.com/spreadsheets/d/1Uogm7SpgWVA4AiP6gqFkluaozFtlaEGMc4K2Mbfee7U/edit#gid=1740497564"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Uogm7SpgWVA4AiP6gqFkluaozFtlaEGMc4K2Mbfee7U/edit#gid=1740497564</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
</div>
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<h1 id="6b1b" class="hz ia ds bk bj ib ic it ie iu ig iv ii iw ik ix im">Unit Test with Qemu Blue Pill
Emulator</h1>
<p id="5521" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm">Replacing the standard math
library by <code class="dj hl hm hn ho b">nano-float</code> is an onerous tasks. How can we really be
sure that the above formulae were <strong class="gb gr">correctly programmed</strong>? And that the
<code class="dj hl hm hn ho b">nano-float</code> computation results (single precision) <strong
class="gb gr">wont deviate too drastically</strong> from the original math functions (double
precision)?</p>
<p id="0cce" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Its not a perfect solution but
we have <strong class="gb gr">Unit Tests for </strong><code
class="dj hl hm hn ho b"><strong class="gb gr">nano-float</strong>: https://github.com/lupyuen/codal-libopencm3/blob/master/lib/nano-float/test/test.c</code>
</p>
<p id="49e8" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">These test cases are meant to be
run again and again to verify that the results are identical whenever we make changes to the code. The
test cases were automatically extracted from the <code class="dj hl hm hn ho b">nano-float</code>
source code by this Google Sheets spreadsheet…</p>
<div class="me mf mg mh mi jx"><a
2021-02-23 17:24:18 +08:00
href="https://docs.google.com/spreadsheets/d/1Uogm7SpgWVA4AiP6gqFkluaozFtlaEGMc4K2Mbfee7U/edit?source=post_page-----55093aab163a----------------------#gid=1740497564"
2021-02-23 09:51:56 +08:00
rel="noopener nofollow">
<section class="ka cl cm ak ce n ar kb kc kd ke kf kg kh ki kj kk kl km kn ko kp">
<div class="kq n co p kr ks">
<h2 class="bj ib kt bl ds">
<div class="de jy ew ex jz ez">nano-float Unit Test</div>
</h2>
</div>
<div class="kw r">
<div class="mj r ky kz la kw lb lc ld"></div>
</div>
</section>
</a></div>
<p id="42c3" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Unit tests are also meant to be
run automatically at every rebuild. But the code requires a Blue Pill to execute. The solution:
<strong class="gb gr">Use the </strong><a
2021-02-23 17:24:18 +08:00
href="http://beckus.github.io/qemu_stm32/"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow"><strong class="gb gr">Qemu Blue
Pill Emulator</strong></a><strong class="gb gr"> to execute the test cases</strong>, by simulating
a Blue Pill in software.</p>
<p id="af40" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">So far the test cases confirm
that Qfplib is accurate up to 6 decimal digits, when compared with the standard math library
(double-precision). Which sounds right because Qfplib uses single-precision math (accurate to 6
decimal digits).</p>
<p id="5738" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">Well cover <strong
class="gb gr">Blue Pill Unit Testing and Blue Pill Emulation</strong> in the next article.</p>
</div>
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="cz ak">
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz ak paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m10.png" /></p>
2021-02-25 21:00:07 +08:00
<figcaption><p><em>Memory usage of the MakeCode application on Blue
2021-02-23 09:51:56 +08:00
Pill, without Qfplib and nano-float. From <a
2021-02-23 17:24:18 +08:00
href="https://docs.google.com/spreadsheets/d/1DWFoh0Ui9j294htHzQrH-s6MuPRXct2zN8M9pj53CBk/edit#gid=381366828&amp;fvid=1359565135"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1DWFoh0Ui9j294htHzQrH-s6MuPRXct2zN8M9pj53CBk/edit#gid=381366828&amp;fvid=1359565135</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
</div>
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<h1 id="1fae" class="hz ia ds bk bj ib ic it ie iu ig iv ii iw ik ix im">How I used Qfplib and
nano-float</h1>
<p id="4874" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm"><a
2021-02-23 17:24:18 +08:00
href="https://makecode.com/docs"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">MakeCode</a> is visual programming
tool for creating embedded programs for microcontrollers (like the BBC micro:bit), simply by dragging
and dropping code blocks in a web browser. Its the perfect way to teach embedded programming to
beginners.</p>
<p id="f798" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><a class="at cg gn go gp gq"
target="_blank" rel="noopener"
2021-02-28 20:43:47 +08:00
href="https://web.archive.org/web/20191204194221/https://medium.com/@ly.lee/work-in-progress-stm32-blue-pill-visual-programming-with-makecode-codal-and-libopencm3-422d308f252e?source=friends_link&sk=b39519335652415d5f4aa17c9e4af1d2">While
2021-02-23 09:51:56 +08:00
porting MakeCode to Blue Pill</a>, I had trouble squeezing all the code into Blue Pills 64 KB ROM.
(The BBC micro:bit has 256 KB of ROM, with plenty of room for large libraries.) After compiling for
Blue Pill, I noticed that the <strong class="gb gr">math libraries were taking huge chunks of ROM
storage</strong> (roughly 17 KB), which you can see in the spreadsheet above. So I made these
changes…</p>
<ol class="">
<li id="725b" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm hd he hf">Using <code
class="dj hl hm hn ho b">__wrap___aeabi_dmul</code> method described earlier, I intercepted the
single-precision and double-precision comparison and arithmetic operations (multiply, divide) and
used Qfplib instead. <a
2021-02-23 17:24:18 +08:00
href="https://github.com/lupyuen/newlib/blob/master/CMakeLists.txt#L28-L61"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank" rel="noopener nofollow">Heres the complete list of
intercepted functions</a>.</li>
<li id="d282" class="fz ga ds bk gb b gc hg ge hh gg hi gi hj gk hk gm hd he hf">I used <code
class="dj hl hm hn ho b">nano-float</code> as a drop-in replacement for the standard math library
<code class="dj hl hm hn ho b">libm.a</code>. So all calls to common math functions like <code
class="dj hl hm hn ho b">sin(), log(), floor()</code>, … were handled by <code
class="dj hl hm hn ho b">nano-float</code>.</li>
</ol>
<p id="5c40" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">After optimisation, the ROM usage
has dropped drastically, as shown below. So MakeCode might actually run on Blue Pill, assuming we
dont need double-precision math. I havent completed my testing of MakeCode on Blue Pill yet — Im
taking a break from the coding and testing to document my MakeCode porting experience, which is what
youre reading now (and more to come).</p>
<p id="063d" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><a class="at cg gn go gp gq"
target="_blank" rel="noopener"
2021-02-25 17:57:35 +08:00
href="https://lupyuen.github.io/articles/stm32-blue-pill-analyse-and-optimise-your-ram-and-rom">Read
2021-02-23 09:51:56 +08:00
about Blue Pill memory optimisation in my previous article</a>.</p>
</div>
</div>
<div class="cz ak">
2021-02-25 21:05:13 +08:00
<div class="figure gs gt gu gv gw cz ak paragraph-image">
2021-02-24 13:02:41 +08:00
<p><img src="https://lupyuen.github.io/images/legacy2/m11.png" /></p>
2021-02-25 16:11:14 +08:00
2021-02-25 21:00:07 +08:00
<figcaption><p><em>Memory usage of the MakeCode application on Blue
2021-02-23 09:51:56 +08:00
Pill, with Qfplib and nano-float. From <a
2021-02-23 17:24:18 +08:00
href="https://docs.google.com/spreadsheets/d/1OmD1XmUQJTIiXklYx-eui27MFBBhnXrCNaJwSUFDiN8/edit#gid=381366828&amp;fvid=1359565135"
2021-02-23 09:51:56 +08:00
class="at cg gn go gp gq" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1OmD1XmUQJTIiXklYx-eui27MFBBhnXrCNaJwSUFDiN8/edit#gid=381366828&amp;fvid=1359565135</a>
2021-02-25 21:00:07 +08:00
</em></p></figcaption>
2021-02-25 21:05:13 +08:00
</div>
2021-02-23 09:51:56 +08:00
</div>
</section>
<hr class="hq et hr hs ht ha hu hv hw hx hy" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dp aj ak">
<h1 id="f67f" class="hz ia ds bk bj ib ic id ie if ig ih ii ij ik il im">The Daring Proposition</h1>
<p id="b9cb" class="fz ga ds bk gb b gc in ge io gg ip gi iq gk ir gm">In this article I have argued
that<strong class="gb gr"> we dont need highly-precise double-precision math libraries all the
time</strong>. Its plausible that <strong class="gb gr">single-precision math (optimised with
Qfplib) is sufficient for IoT and for Blue Pill embedded programs</strong>. If we accept this, then
the lowly Blue Pill microcontroller will be able to run math programs that were previously too big to
fit on Blue Pill. Like the MakeCode visual programming tool.</p>
<p id="eda3" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm">But this needs to be validated
through real-world testing (Ill be validating shortly through MakeCode). For the daring embedded
programmers… All the code you need is already in this article, so go ahead and try it out!</p>
<p id="0017" class="fz ga ds bk gb b gc gd ge gf gg gh gi gj gk gl gm"><em class="hp">Many thanks to
Fabien Petitgrand for the precious feedback</em></p>
</div>
</div>
</section>
</div>
</article>
2021-02-23 09:50:06 +08:00
</div>
</div>
2021-02-26 20:10:47 +08:00
<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>
2021-02-23 09:51:56 +08:00
</body>
</html>
<!--
2021-02-23 09:50:06 +08:00
FILE ARCHIVED ON 19:42:30 Dec 04, 2019 AND RETRIEVED FROM THE
INTERNET ARCHIVE ON 01:30:43 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.014
captures_list: 100.415
load_resource: 57.386
RedisCDXSource: 26.735
LoadShardBlock: 44.154 (3)
exclusion.robots: 0.514
PetaboxLoader3.datanode: 54.081 (4)
exclusion.robots.policy: 0.495
CDXLines.iter: 25.262 (3)
PetaboxLoader3.resolve: 38.045
-->