lupyuen.org/articles/low-power-nb-iot-on-stm32-blue-pill-with-apache-mynewt-and-embedded-rust.html

1327 lines
No EOL
88 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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/low-power-nb-iot-on-stm32-blue-pill-with-apache-mynewt-and-embedded-rust.html" />
<!-- End Wayback Rewrite JS Include -->
<title data-rh="true">Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust</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-10-18T05:45:42.236Z" />
<meta data-rh="true" name="title"
content="Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust" />
<meta data-rh="true" property="og:title"
content="Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust" />
<meta data-rh="true" property="twitter:title"
content="Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust" />
<meta data-rh="true" name="description"
content="How much power do Quectel NB-IoT modules consume? Lets find out with the RuiDeng DPS 3005" />
<meta data-rh="true" property="og:description"
content="How much power do Quectel NB-IoT modules consume? Lets find out with the RuiDeng DPS 3005" />
<meta data-rh="true" property="twitter:description"
content="How much power do Quectel NB-IoT modules consume? Lets find out with the RuiDeng DPS 3005" />
<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="16 min read" />
<meta property="og:image"
content="https://lupyuen.github.io/images/legacy/t1.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/legacy/t1.png" /></p>
<figcaption><p><em>RuiDeng DPS 3005 Power Monitor measuring the
power consumption of STM32 Blue Pill connected to Quectel BC95-G NB-IoT module</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<div>
<div id="1bb6" class="ea eb ec bk ed b ee ef eg eh ei ej ek">
<h1 class="ed b ee el ec">Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust
</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/low-power-nb-iot-on-stm32-blue-pill-with-apache-mynewt-and-embedded-rust">
30 Aug 2019</a> <!-- -->·
<!-- -->
<!-- -->16
<!-- --> min read
</div>
</span></span>
</div>
</div>
</div>
</div>
</div>
<p id="9328" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In this article well learn to
optimise the power consumption of the <a class="at cg gv gw gx gy" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">NB-IoT
Sensor Application in the previous tutorial</a> from this jagged power-hungry mess…</p>
</div>
</div>
<div class="cz ak">
<div class="figure gz ha hb hc hd cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t2.png" /></p>
<figcaption><p><em>Power consumed by our IoT sensor device before
optimisation. From <a
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing</a>
</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="2b80" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To these well-disciplined bars…
</p>
</div>
</div>
<div class="cz ak">
<div class="figure gz ha hb hc hd cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t3.png" /></p>
<figcaption><p><em>Power consumed by our IoT sensor device after
optimisation. From <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="e50d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Its a simple application (coded
in Embedded Rust) that polls Blue Pills internal temperature sensor and transmits the sensor data to
a server over NB-IoT.</p>
<p id="8c29" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The power optimisation (recorded
with a $25 <a
href="https://www.aliexpress.com/item/32684316119.html"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">RuiDeng DPS 3005 Power
Monitor</a>) becomes more apparent when we compare the charts side by side…</p>
</div>
</div>
<div class="cz ak">
<div class="figure gz ha hb hc hd cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t4.png" /></p>
<figcaption><p><em>Power consumed by our IoT sensor device before
and after optimisation. From <a
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing</a>
and <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="49c3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">From the charts above we can see
the secret to long battery life is this…</p>
<p id="9c97" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Stay in Deep Sleep
for as long as possible!</em></p>
<p id="7f4c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Our sensor device doesnt need to
transmit sensor data every second. When it sleeps for a minute or more between transmissions, the
battery life is dramatically increased.</p>
<p id="2eef" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">However we need to be sure that
our NB-IoT module wont become totally disconnected from the network as Blue Pill sleeps. We have the
solution for that.</p>
<p id="2091" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Can we go below 3
milliAmperes?</em></p>
<p id="2774" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Yes we can! Scrutinise the photo
at the top of the article… Notice that TWO power LEDs are still lit: Power LED for Blue Pill and Power
LED for the NB-IoT breakout board.</p>
<p id="1c6e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The two LEDs are always lit, even
during Deep Sleep. If we desolder the two LEDs, the current consumed will surely drop way below 3
milliAmperes. My colleague Upton Lai has previously <a
href="https://www.linkedin.com/feed/update/urn:li:activity:6473079182715863040/"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">desoldered the Blue Pill Power
LED</a> and recorded <strong class="gj hi">10 microAmperes</strong> of power consumption in Deep
Sleep! (Without NB-IoT)</p>
<p id="cfd3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But for now well keep the LEDs…
My intent is to let you recreate this experiment easily using off-the-shelf hardware. So that you can
follow me and discover for yourself the right way to conserve power.</p>
<p id="25bf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Theres something
odd about the Current values in the charts…</em></p>
<p id="173c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Yes the charts look different
from High School Physics because I rendered the charts (in Google Sheets) using a <strong
class="gj hi">Logarithmic Scale</strong>.</p>
<p id="5562" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This makes the chart look more
scenic and poetic like a rolling hill… instead of a desolate landscape with steep mountains and
treacherous crevices. And I assure you that no values have been altered. (Just check the Google
Sheets)</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t5.png" /></p>
<figcaption><p><em>Logarithmic Scale vs Normal Scale. From <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="f913" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Quectel NB-IoT Power
Consumption</h1>
<p id="1439" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Its important to power down the
NB-IoT module when we have transmitted the data: <code class="dm ix iy iz ja b">AT+CFUN=0</code></p>
<p id="9a0e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">According to the documentation
for the above command in <em class="hh">“Quectel BC95-G &amp; BC68 AT Commands Manual”…</em></p>
<blockquote class="jb jc jd">
<p id="b54d" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">Deep sleep mode will be entered
when the system is quiescent, but only if it has been enabled by the network.</p>
</blockquote>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t6.png" /></p>
<figcaption><p><em>Optimised NB-IoT Power Consumption. From <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="7d91" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Instead of keeping our device
always connected to NB-IoT, we would have to reattach to the NB-IoT network (<code
class="dm ix iy iz ja b">AT+CGATT=1</code>) every time we wake up. Attaching to the NB-IoT network
may take a few seconds, consuming 40 milliAmperes throughout.</p>
<p id="e387" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">(Mr Stefan de
Lange kindly pointed out that we could attach to the NB-IoT network at power on instead of wakeup.
Well explore that in a future article. Thanks Stefan!)</em></p>
<p id="841a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The actual NB-IoT transmission
takes a split second, reaching peaks of about 400 milliAmperes.</p>
<p id="4c43" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres the log from my optimised
Blue Pill, chronicling the events after Deep Sleep Wakeup…</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/6b7e491bb735db1d0cc42694c1f6180e.js"></script></p>
<figcaption><p><em>Blue Pill Log from <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/logs/standalone-node-standby.log"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/logs/standalone-node-standby.log</a>
</em></p></figcaption>
</div>
<p id="80e1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that we used the <code
class="dm ix iy iz ja b">NSOSTF</code> command instead of <code
class="dm ix iy iz ja b">NSOST</code> to send a UDP packet with flags. In my previous article we
used…</p>
<pre
class="gz ha hb hc hd jh ji jj"><span id="544b" class="jk if ec bk ja b ds jl jm r jn">AT+NSOST=1,104.199.85.211,5683,174,(data)…</span></pre>
<p id="8f7e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Now we use…</p>
<pre
class="gz ha hb hc hd jh ji jj"><span id="4efc" class="jk if ec bk ja b ds jl jm r jn">AT+<strong class="ja hi">NSOSTF</strong>=1,104.199.85.211,5683,<strong class="ja hi">0x200</strong>,174,(data)…</span></pre>
<p id="6819" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The extra parameter <code
class="dm ix iy iz ja b">0x200</code> is the “Early Release” flag… It tells the NB-IoT network that
we are not expecting any response messages. So we can safely go to sleep and save power.</p>
<p id="b6cf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The “Early Release” flag was
recommended by Mr Henk Vergonet at <a
href="https://forum.iot.t-mobile.nl/topic/278/how-much-battery-lifetime-can-we-expect-with-a-sara-n200-module-on-our-iot-network/2"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">T-Mobile Netherlands</a></p>
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv jw jx jy jz ka paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t7.png" /></p>
<figcaption><p><em>From <a
href="https://gist.github.com/lupyuen/ef51005c6c965f6a21d496ad24eacc51"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://gist.github.com/lupyuen/ef51005c6c965f6a21d496ad24eacc51</a>
</em></p></figcaption>
</div>
<p id="bf4c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres a valuable tip from Mr
Stefan de Lange…</p>
<blockquote class="jb jc jd">
<p id="9c70" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hi">ECL is a
key parameter to monitor</strong>. It determines the amount of repetitions the module will do. So
instead of sending a message once the module might send the message 10, 20 or 30 times to make sure
it arrives.</p>
</blockquote>
<p id="e985" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The ECL is displayed when we send
the <code class="dm ix iy iz ja b">AT+NUESTATS</code> command.</p>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="f9e3" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">When Apache Mynewt Idles</h1>
<p id="265a" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Lets dive deep into Mynewt and
understand what happens when our Blue Pill is idle, waiting to poll the temperature sensor or waiting
for an NB-IoT command to complete…</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/2eec3bc048bf3349cc14c585473456fb.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c</a>
</em></p></figcaption>
</div>
<p id="bca3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Arm processor inside our Blue
Pill has a built-in <a
href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/ar01s02s08.html"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj hi">SysTick
Timer</strong></a>. Its used by Mynewt to perform multitasking. In the code above, Mynewt
configures the SysTick Timer to generate an interrupt every millisecond.</p>
<p id="4c91" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When the millisecond interrupt is
triggered, Mynewt checks whether it should continue running the current task, or switch to a
higher-priority task. If there are no tasks ready to run (which will most likely be the case for our
device), Mynewt still keeps <em class="hh">checking every single millisecond</em>. This is not good
for battery life.</p>
<p id="077c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">What happens when there are no
tasks ready to run? Mynewt calls <code class="dm ix iy iz ja b">os_task_idle()</code>, passing the
number of ticks that it should stay idle. (1 tick = 1 millisecond)</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/8d6744ffdcb3871d0f36371344796459.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c</a>
</em></p></figcaption>
</div>
<p id="85e2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Mynewt computes the idle time
based on the list of pending tasks. So if the temperature sensor is supposed to be polled every 10
seconds, Mynewt knows that after polling the sensor, it should stay idle for roughly 10,000 ticks
before resuming the polling task.</p>
<p id="709f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
class="dm ix iy iz ja b">WFI</code> in the code above is the Arm instruction “<strong
class="gj hi">Wait For Interrupt</strong>”. It means that the Arm processor will go into a
power-saving quick nap (not Deep Sleep) until an interrupt occurs.</p>
<p id="e6ad" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">BUT… remember that our <em
class="hh">SysTick Interrupt occurs every millisecond</em>… so our Blue Pill doesnt sleep much!</p>
<p id="5391" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres proof of that… Watch what
happens when we add some debug output to <code class="dm ix iy iz ja b">os_task_idle()</code>...</p>
</div>
</div>
<div class="cz ak">
<div class="figure gz ha hb hc hd cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t8.png" /></p>
<figcaption><p><em>Proof that Blue Pill wakes up every millisecond
</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<blockquote class="jb jc jd">
<p id="5515" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu"><em class="bk">💎</em> <strong
class="gj hi">“Heisenbergs Uncertainty Principle” for Embedded Systems…</strong></p>
<p id="3f5f" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">Dont try at home what you see
above! Its NOT a good idea to display debug messages on the console when youre deep inside the
operating system… like in the Task Scheduling code above.</p>
<p id="35ce" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">How did I do it? My <code
class="dm ix iy iz ja b">console_print()</code> functions were specially designed to buffer output
messages into RAM (using <code class="dm ix iy iz ja b">mbufs</code>). So no I/O is performed by the
code above… Until the application flushes the console output.</p>
<p id="51a0" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">If this debug code used a
normal console I/O call, it would interfere with the <code
class="dm ix iy iz ja b">os_task_idle()</code> operation (it might get deadlocked). So when you
insert debug code to observe whats happening deep inside your microcontroller, you might actually
affect the outcome.</p>
<p id="8794" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">Hence some folks call this “<a
href="https://en.wikipedia.org/wiki/Uncertainty_principle"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><em class="bk">Heisenbergs
Uncertainty Principle</em></a>” (like in Quantum Mechanics)… Beware of Heisenberg! :-)</p>
</blockquote>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="7319" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Going Tickless on Apache Mynewt
with Real Time Clock</h1>
<p id="ab59" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Heres the problem: We would like
to sleep longer and conserve power… But the SysTick Timer keeps waking us up every millisecond. Can we
do without SysTick? Can we go… <strong class="gj hi">Tickless</strong>? Yes we can!</p>
<p id="6a53" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Blue Pill and other STM32
microcontrollers have an onboard <strong class="gj hi">Real Time Clock</strong>. Unlike a real wall
clock, the Real Time Clock doesnt tell you the time of the day. But its useful for two things…</p>
<p id="ed21" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<strong
class="gj hi">Counting the ticks</strong> that have elapsed since we powered on our device. It keeps
counting even in Deep Sleep!</p>
<p id="3e7d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<strong
class="gj hi">Triggering an Alarm Interrupt</strong> at a time (in ticks) that we set</p>
<p id="3962" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Remember that Mynewt calls <code
class="dm ix iy iz ja b">os_task_idle(X)</code> when its ready to sleep for <code
class="dm ix iy iz ja b">X</code> milliseconds. Why dont we set the Real Time Clock Alarm to wake
us up in <code class="dm ix iy iz ja b">X</code> milliseconds?</p>
<p id="ec96" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">So in the optimised task
scheduler for Mynewt, we eliminate SysTick altogether, replaced by the Real Time Clock Alarm. <code
class="dm ix iy iz ja b">os_task_idle()</code> now calls <code
class="dm ix iy iz ja b">power_sleep()</code></p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/75b96f3a3da157d0b8cc4e9cb3c05bb0.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c</a>
</em></p></figcaption>
</div>
<p id="ca30" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">What about <code
class="dm ix iy iz ja b">WFI</code>, the Wait For Interrupt instruction that we saw earlier? It
still works! Because the Real Time Clock triggers an interrupt (Alarm Interrupt) when the time is up.
Heres how we call <code class="dm ix iy iz ja b">WFI</code> for a quick nap (<strong
class="gj hi">Sleep Now Mode</strong>)…</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/68c5ac770b56aa218da615df69d5ae27.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c</a>
</em></p></figcaption>
</div>
<p id="5c95" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <code
class="dm ix iy iz ja b">power_sleep()</code> function calls <code
class="dm ix iy iz ja b">target_enter_sleep_mode()</code> and <code
class="dm ix iy iz ja b">WFI</code> for a quick nap. When we have finished transmitting our sensor
data over NB-IoT, we could actually take a longer nap… this is the <strong class="gj hi">Deep Sleep
Standby Mode</strong> we saw earlier… the one that consumes only 3 milliAmperes! (With the power
LEDs still lit) Well cover Deep Sleep Standby Mode in a while.</p>
<p id="fbc0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Zephyr RTOS has a good
explanation of <a
href="https://docs.zephyrproject.org/1.13.0/subsystems/power_management.html#tickless-idle"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Tickless Task Scheduling here</a>
</p>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="2da0" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Power Saving Modes on Blue Pill
</h1>
<p id="e8d5" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">There are <a
href="https://www.st.com/content/ccc/resource/technical/document/application_note/ff/0a/dc/d2/5e/f5/4b/5a/CD00171691.pdf/files/CD00171691.pdf/jcr:content/translations/en.CD00171691.pdf"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">three power saving modes</a> on
Blue Pill…</p>
<p id="0c62" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<strong class="gj hi">Sleep
Now Mode (10 milliAmperes)</strong>: This is the <code class="dm ix iy iz ja b">WFI</code> (Wait For
Interrupt) instruction thats implemented in the Arm processor. It puts Blue Pill into a light nap
that still consumes substantial power. Thats because the Blue Pill peripherals (like the UART port)
are still powered on.</p>
<p id="343c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<strong class="gj hi">Deep
Sleep Stop Mode</strong>: Similar to Sleep Now Mode, except that the peripherals (like UART) are
powered down. Consumes less power than Sleep Now Mode but more power than Deep Sleep Standby Mode. On
wakeup, Blue Pill resumes execution with the peripherals powered down. <em class="hh">RAM is
preserved.</em></p>
<p id="0078" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<strong class="gj hi">Deep
Sleep Standby Mode (3 milliAmperes, with power LEDs still lit)</strong>: The ultimate low power
mode. All peripherals powered down (same as Deep Sleep Stop Mode). BUT on wakeup, <em class="hh">Blue
Pill restarts</em> as though it was just powered on. <em class="hh">Everything in RAM is lost.</em>
</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t9.png" /></p>
<figcaption><p><em>Sleep Now Mode vs Deep Sleep Standby Mode.
From <a
href="https://docs.google.com/spreadsheets/d/1ygUzKYWTo-BSSvKzL3J6ub3o4-7sVrjMUyvGLdAsHJ0/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1ygUzKYWTo-BSSvKzL3J6ub3o4-7sVrjMUyvGLdAsHJ0/edit?usp=sharing</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="db8b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This may sound odd… But Deep
Sleep <strong class="gj hi">Standby Mode</strong> (the ultimate power saver) is <em class="hh">easier
to code</em> than Deep Sleep <strong class="gj hi">Stop Mode</strong>.</p>
<p id="5370" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">With Stop Mode we need to power
on the peripherals ourselves when waking up… And it gets complicated. With Standby Mode, we just
pretend that our Blue Pill has just powered on… Except that we can check a flag to distinguish whether
its a Power On or a Standby Wakeup.</p>
<p id="7869" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres how we check the flag…</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/9c37accdc0fc9315390dd8073a1b886a.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c</a>
</em></p></figcaption>
</div>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="761e" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Embedded Rust Application For
Low Power</h1>
<p id="ce4a" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Remember from our previous
tutorial that the IoT Sensor Application was developed in Rust. <em class="hh">Is Rust really suitable
for Low Power Devices? Does Rust make our device less power-efficient?</em></p>
<p id="6e25" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Im happy to report that <em
class="hh">Rust is just as power-efficient as C!</em> Thats because Rust is compiled into optimised
Arm machine code, so theres no extra execution overhead when our application is written in Rust.</p>
<p id="2b68" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Rust application logic was
tweaked slightly to make it more power-efficient…</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/ae5e50c2aa618a377e4ae367210303d4.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs</a>
</em></p></figcaption>
</div>
<p id="44e0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The top half of the function
<code class="dm ix iy iz ja b">start_sensor_listener()</code> is exactly the same as before. When our
device is powered up, we instruct Mynewt to poll the temperature sensor every 20 seconds. Mynewt
passes the sensor data to our function <code class="dm ix iy iz ja b">handle_sensor_data()</code> for
transmitting to the server.</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/e691257e5aa0dc589fff126961203622.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs</a>
</em></p></figcaption>
</div>
<p id="53c9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The lower half of <code
class="dm ix iy iz ja b">start_sensor_listener()</code> introduces a minor twist… When our device
wakes up from Deep Sleep Standby Mode, we read the temperature sensor directly, without polling. And
we transmit the sensor data the same way, via <code
class="dm ix iy iz ja b">handle_sensor_data()</code>.</p>
<p id="1e33" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This keeps our device fully
occupied during the precious few seconds that our device is awake, until it falls into Deep Sleep.</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/51bc6ecec5c9edd01dee5c01882fe61f.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/sensor_network/src/sensor_network.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/sensor_network/src/sensor_network.c</a>
</em></p></figcaption>
</div>
<p id="3323" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <strong class="gj hi">Sensor
Network Library</strong> (written in C) has been optimised for low power operation as well. During
wakeup, the function attaches to the NB-IoT network and doesnt return until it completes. (Previously
we started a background task to attach to the NB-IoT network so that we could run other tasks.)</p>
<p id="8b91" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This chart illustrates the power
consumed when our Blue Pill polls the onboard temperature sensor vs reading the sensor directly.</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t10.png" /></p>
<figcaption><p><em>Polling vs Reading the temperature sensor.
From <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="255c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The code changes are really
minor. Mynewts Sensor Framework has done an excellent job in managing the access to sensors in a
consistent, reusable way, even for Low Power. And Rust makes the code look much cleaner and simpler
than C.</p>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="7068" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Measure Power Consumption with
RuiDeng DPS 3005 Power Monitor</h1>
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t11.jpeg" /></p>
<figcaption><p><em>RuiDeng DPS 3005 Power Monitor measuring the
power consumption of STM32 Blue Pill connected to Quectel BC95-G NB-IoT module</em></p></figcaption>
</div>
<p id="4453" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Now lets run our IoT Sensor
Device and measure the power consumption with <a
href="https://www.aliexpress.com/item/32684316119.html"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">RuiDeng DPS 3005 Power
Monitor</a>!</p>
<p id="5b29" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><a class="at cg gv gw gx gy"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/connect-the-nb-iot-hardware-stm32-blue-pill-and-quectel-bc95-g-module">Follow
the instructions here</a> to connect Blue Pill to the NB-IoT module and ST-Link.</p>
<p id="45f3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Lets look at inputs and outputs
for the Power Monitor…</p>
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv jw jx jy jz ka paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t12.png" /></p>
<figcaption><p><em>Inputs and Outputs for RuiDeng DPS 3005 Power
Monitor</em></p></figcaption>
</div>
<p id="a660" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hi">Inputs at
Left Side (</strong><code
class="dm ix iy iz ja b"><strong class="gj hi">IN+, IN-</strong></code><strong
class="gj hi">)</strong>: Connect to the DC power supply. I used two 18650 lithium ion 3.7 Volt
batteries connected in series. Total 7.2 Volts, sufficient for providing 5 Volts to our Blue Pill and
NB-IoT module.</p>
<p id="4d35" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hi">Outputs at
Right Side (</strong><code
class="dm ix iy iz ja b"><strong class="gj hi">OUT-, OUT+</strong></code><strong
class="gj hi">)</strong>: Connect to the Blue Pill and NB-IoT module. This will be the 5-Volt power
source for our Blue Pill and NB-IoT module.</p>
<p id="5be8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres how I powered my Power
Monitor…</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t13.jpeg" /></p>
<figcaption><p><em>RuiDeng DPS 3005 Power Monitor powered by
two 18650 lithium ion 3.7 Volt batteries</em></p></figcaption>
</div>
<div class="figure da cz hs ht 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="kp">
<div id="0a63" class="kq kr ks bk ed b kt ku kv kw kx ky gu">
<p class="ed b kz la bo">When Flashing Firmware…</p>
</div>
</blockquote>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure lb lc ld le lf cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t14.jpeg" /></p>
<figcaption><p><em>Blue Pill and NB-IoT Module connected to
ST-Link</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv lh li lj lk ka">
<p><script src="https://gist.github.com/lupyuen/58e4584448ab90098b033e996f228bca.js"></script></p>
</div>
<p id="73d3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When flashing the firmware to
Blue Pill, connect ST-Link to Blue Pill and the NB-IoT module as shown.</p>
<p id="8ed1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that the NB-IoT module is
powered by the 5V pin from ST-Link.</p>
<p id="dc03" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Blue Pills 5V pin should be
disconnected.</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure gz ha hb hc hd cz hs ht 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="kp">
<div id="6218" class="kq kr ks bk ed b kt ku kv kw kx ky gu">
<p class="ed b kz la bo">When Monitoring Power Consumption…</p>
</div>
</blockquote>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure lb lc ld le lf cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t15.jpeg" /></p>
<figcaption><p><em>Blue Pill and NB-IoT Module connected to
RuiDeng DPS 3005 Power Monitor</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv lh li lj lk ka">
<p><script src="https://gist.github.com/lupyuen/9890b3511728c9e5ddcc0b49a35d5a91.js"></script></p>
</div>
<p id="cece" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When monitoring the power
consumption, disconnect ST-Link.</p>
<p id="697c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Connect Blue Pills 5V pin to the
Power Meter.</p>
<p id="eae9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The NB-IoT module should be
powered by the Power Meter as well.</p>
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv jw jx jy jz ka paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t16.jpeg" /></p>
<figcaption><p><em>Bluetooth module for DPS 3005 Power Monitor
</em></p></figcaption>
</div>
<p id="0487" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Make sure your DPS 3005 Power
Monitor is bundled with a <strong class="gj hi">Bluetooth module</strong>.</p>
<p id="ba98" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The module connects the Power
Monitor to your Windows computer wirelessly for recording data power consumption data (at 1 sample per
second). Sadly I couldnt connect from macOS.</p>
<p id="754a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">RuiDengs software for DPS 3005
did not allow recording of data, so I used the open-source <code
class="dm ix iy iz ja b"><a href="https://github.com/lambcutlet/DPS5005_pyGUI" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">DPS5005_pyGUI</a></code>
data logger.</p>
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t17.png" /></p>
<figcaption><p><em>DPS5005_pyGUI data logger: <a
href="https://github.com/lambcutlet/DPS5005_pyGUI"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lambcutlet/DPS5005_pyGUI</a></em></p></figcaption>
</div>
<p id="4539" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The low power version of Apache
Mynewt and the updated Embedded Rust application may be installed <a class="at cg gv gw gx gy"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/install-low-power-apache-mynewt-and-embedded-rust-for-visual-studio-code-on-windows">according
to these instructions</a>.</p>
<div class="lp lq lr ls lt lu"><a rel="noopener"
href="https://lupyuen.github.io/articles/install-low-power-apache-mynewt-and-embedded-rust-for-visual-studio-code-on-windows">
<section class="lx cl cm ak ce n ar ly lz ma mb mc md me mf mg mh mi mj mk ml mm">
<div class="mn n co p mo mp">
<h2 class="bj ig mq bl ec">
<div class="di lv fe ff lw fh">Install Low Power Apache Mynewt and Embedded Rust for Visual
Studio Code on Windows</div>
</h2>
</div>
<div class="mt r">
<div class="mu r mv mw mx mt my mz na"></div>
</div>
</section>
</a></div>
<p id="ad11" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Is 1 sample per
second sufficient for understanding the power consumption?</em></p>
<p id="d3b4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Honestly, no. There are peaks in
our power consumption during NB-IoT transmission. The peaks seem to reach 400 milliAmperes… But
because the sampling rate is so low, the peaks could possibly be much higher than that.</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t18.png" /></p>
<figcaption><p><em>Peaks in NB-IoT Power Consumption. From <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="a06b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Nonetheless, we now have a $25
setup that lets us quickly tweak our firmware and check whether the tweaks actually improve power
consumption. So the RuiDeng Power Monitor is an affordable way to guide us towards the right direction
to reduce power consumption. <em class="hh">When you have finalised the firmware, remember to use the
proper equipment to measure the real power consumption!</em></p>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="a7b7" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">The Results</h1>
<p id="ea41" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">After optimising the power
consumption, how much longer did the battery last? A whopping… <em class="hh">26% increase in battery
life!</em></p>
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t19.png" /></p>
<figcaption><p><em>Computed battery life for our IoT sensor
device. From <a
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit#gid=1065153023"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit#gid=1065153023</a>
and <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1872735739"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1872735739</a>
</em></p></figcaption>
</div>
<p id="41b9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But its a good start! Remember
that the power LEDs are still lit. And we have achieved flat lines of power usage during Deep Sleep.
</p>
</div>
</div>
<div class="cz ak">
<div class="figure gz ha hb hc hd cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t20.png" /></p>
<figcaption><p><em>Power consumed by our IoT sensor device before
and after optimisation. From <a
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing</a>
and <a
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="710a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Right now our Blue Pill wakes up
every 1 minute or so… If we could extend the Deep Sleep to 10 minutes or longer, we should get much
lower overall power consumption.</p>
<p id="74da" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Unfortunately I couldnt get Blue
Pill to sleep beyond 1 minute… <em class="hh">Something is still waking it up. </em>Another timer? Or
NB-IoT?</p>
<p id="1063" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">I invite you to reproduce the
same setup with the steps I have described… And help me solve the mystery! (Or work around it… See the
<em class="hh">“Backup Registers”</em> section below)</p>
<p id="128a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But I hope you now have a deeper
appreciation of all the components that make an IoT Sensor truly Low Power… <strong class="gj hi"><em
class="hh">the Network (NB-IoT), the Microcontroller (STM32) and the Operating System
(Mynewt)!</em></strong></p>
<p id="132a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Many thanks to
</em><a href="https://www.starhub.com/"
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj hi"><em
class="hh">StarHub</em></strong></a><em class="hh"> for sponsoring the NB-IoT SIM that I used
for this article!</em></p>
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t21.jpg" /></p>
<figcaption><p><em>Final data collection with RuiDeng DPS 3005
Power Monitor connected to STM32 Blue Pill and Quectel BC95-G NB-IoT module. The Bluetooth module
for the Power Monitor is in the centre (green board with red LED).</em></p></figcaption>
</div>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="c98d" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Main and
Backup Power</h1>
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t22.png" /></p>
<figcaption><p><em>From “RM0008 Reference manual for
STM32F103xx”: <a
href="https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf</a>
</em></p></figcaption>
</div>
<p id="b1b7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Lets study the power input for
<strong class="gj hi">STM32F103C8T6</strong>, the STM32 microcontroller at the heart of Blue Pill.
Most parts of STM32F103C8T6 are powered by the <strong class="gj hi">Main Power </strong>(<code
class="dm ix iy iz ja b">VDD</code> in the above diagram).</p>
<p id="21d1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">STM32F103C8T6 has a <strong
class="gj hi">Backup Domain </strong>(highlighted in red)<strong class="gj hi"> </strong>that may be
powered by Main Power <code class="dm ix iy iz ja b">VDD</code> or <strong class="gj hi">Backup
Power</strong> <code class="dm ix iy iz ja b">VBAT</code>. The Backup Domain contains the minimum
components essential for Deep Sleep, such as the Real Time Clock.</p>
<p id="11df" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This means that its possible to
sustain Blue Pill in Deep Sleep just by supplying a bit of Backup Power to the <code
class="dm ix iy iz ja b">VBAT</code> pin, while the rest of Blue Pill (running on Main Power) is
powered down.</p>
<p id="8ef7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Everything in the Backup Domain
continues to operate as long as Backup Power is available. Whats inside the Backup Domain?</p>
<p id="29cf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<strong class="gj hi">Low
Speed External (LSE) Oscillator</strong>: This generates the ticks thats needed by the Real Time
Clock to track time accurately during Deep Sleep</p>
<p id="8b86" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<strong class="gj hi">Backup
Registers (BKP)</strong>: These are ten 16-bit registers that we may use to store 20 bytes of data.
The contents of the registers will be preserved across restarts and wakeups, as long as Backup Power
is available. Well see later how Backup Registers may be used.</p>
<p id="f469" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<strong class="gj hi">Backup
Domain Control Register (BDCR)</strong>: This register is used to configure the LSE Oscillator and
Real Time Clock.</p>
<p id="7d9a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">4<strong class="gj hi">Real
Time Clock (RTC)</strong>: This is needed to count the ticks produced by the LSE Oscillator and
track the elapsed time accurately. It also wakes up the microcontroller at the preset alarm time.</p>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="823a" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Configure
the Real Time Clock</h1>
<p id="ceea" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">This section explains how we
configured the Real Time Clock on Blue Pill. The <code class="dm ix iy iz ja b">alarm_setup()</code>
code looks tricky so well study this step by step.</p>
<p id="c8b4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <code
class="dm ix iy iz ja b">alarm_setup()</code> function is called at startup and wakeup by <code
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/hal_os_tick.c" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">__wrap_os_tick_init</a>()</code>,
which is the intercepted version of <code class="dm ix iy iz ja b">os_tick_init()</code> that well
see in the section<em class="hh"> “Advanced Topic: Patch Mynewt OS Functions”</em> below.</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/9cdbe047881bf69ee8bf63b95d1b78bb.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
</em></p></figcaption>
</div>
<p id="3dc1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Blue Pill has three <strong
class="gj hi">Oscillator Clocks</strong>: <strong class="gj hi">HSE, LSE and LSI</strong>. These are
primitive clocks, good for producing ticks only. We may select one of these Oscillator Clocks to drive
the Real Time Clock and trigger the Deep Sleep wakeup alarm.</p>
<p id="9bd3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<strong class="gj hi">High
Speed External (HSE)</strong> is the fastest clock (8 MHz crystal oscillator)… But also needs the
most power. HSE uses only Main Power, doesnt work on Backup Power. So when we sleep and switch to
Backup Power, it stops. Not suitable for setting the Deep Sleep alarm.</p>
<p id="5cd2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<strong class="gj hi">Low
Speed Internal (LSI) </strong>is a slower clock (~40 kHz RC oscillator) but it also runs on Main
Power, not Backup Power. So its not suitable for setting the Deep Sleep alarm either.</p>
<p id="38ca" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<strong class="gj hi">Low
Speed External (LSE)</strong> (32.768 kHz crystal oscillator) is the best choice because it works on
Backup Power (assuming that our Blue Pill has a Backup Power source when it goes into Deep Sleep)</p>
<p id="9028" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Whats “<strong
class="gj hi">Prescaling</strong>”? Something you do on a fish? No, prescaling lets us run the Real
Time Clock as a fraction of the HSE / LSE / LSI clock speeds. So when we prescale LSE by 32, we run
the Real Time Clock at 1 tick per millisecond. (LSE ticks natively at 32.768 kHz, or 32,768 ticks per
second)</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/94abd5008e4403a9e51b919d84cb5217.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
</em></p></figcaption>
</div>
<p id="881e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Real Time Clock may be used in 3
ways to trigger interrupts…</p>
<p id="955c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<strong class="gj hi">After a
preset number of ticks</strong> (<code class="dm ix iy iz ja b">RTC_SEC</code>). So that the STM32
microcontrollers Real Time Clock may be used like the Arm processors SysTick Timer.</p>
<p id="ff5b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<strong class="gj hi">At a
preset alarm time</strong> (<code class="dm ix iy iz ja b">RTC_ALR</code>). Were using this to wake
up from Deep Sleep.</p>
<p id="e2e7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<strong class="gj hi">Upon
overflow</strong> (<code class="dm ix iy iz ja b">RTC_OW</code>). The Real Time Clock is a 32-bit
counter that counts the number of elapsed ticks from 0 to 4,294,967,295. When the counter overflows,
the Real Time Clock triggers this interrupt so that the operating system can do the necessary time
adjustments.</p>
<p id="40eb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Well be using only the Alarm
Interrupt <code class="dm ix iy iz ja b">RTC_ALR</code>. When the alarm goes off, the Arm processor
will call our function <code class="dm ix iy iz ja b">rtc_alarm_isr()</code></p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/90d67994a7639cbff8a690c16c76c363.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
</em></p></figcaption>
</div>
<p id="d6a1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">At power on we switch on the Real
Time Clock and set the counter value to 0 (<code class="dm ix iy iz ja b">rtc_set_counter_val</code>).
This is the counter well be using to track the elapsed time (as millisecond ticks) in our
application.</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/f8ca47d25bdfea6147ca02b017e6c18d.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
</em></p></figcaption>
</div>
<p id="546d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">During wakeup from Deep Sleep we
dont reset the Real Time Clock counter. That way we can track the elapsed time as Blue Pill sleeps.
Remember that the Real Time Clock keeps counting the ticks during Deep Sleep (powered by Backup
Power).</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/1de1451256e737806ff2dda3ee364b39.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
</em></p></figcaption>
</div>
<p id="7675" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">For Deep Sleep Stop Mode: The
External Interrupt (EXTI) must be configured so that the Alarm Interrupt will wake us up (<code
class="dm ix iy iz ja b">exti_set_trigger</code>). This is not necessary for Deep Sleep Standby
Mode.</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/91fec08b925107d32905727fc61bfae6.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
</em></p></figcaption>
</div>
<p id="e923" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Once we enable the Alarm
Interrupt via <code class="dm ix iy iz ja b">rtc_interrupt_enable(RTC_ALR)</code>, the alarm becomes
operational. We will call <code class="dm ix iy iz ja b">rtc_set_alarm_time()</code> to set the alarm
time (in ticks). When the alarm goes off, our function <code
class="dm ix iy iz ja b">rtc_alarm_isr()</code> will be called.</p>
<p id="3ae2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres how we set the alarm time
before entering Deep Sleep…</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/19229ac27fb794a5c6be8119d5606fdd.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
</em></p></figcaption>
</div>
</div>
</div>
<div class="cz ak">
<div class="figure lb lc ld le lf cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/t23.png" /></p>
<figcaption><p><em>HSE, LSE and LSI clocks on STM32 Blue Pill
</em></p></figcaption>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="d2c0" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Backup
Registers</h1>
<p id="930d" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Heres the problem: Blue Pill
wakes up from Deep Sleep Standby Mode with amnesia… It doesnt know what it was doing before it fell
into Deep Sleep, since the RAM has been erased. <em class="hh">How can we make Blue Pill memorise some
state information so that it can resume working after waking up? Without writing to Flash ROM?</em>
</p>
<p id="0481" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Solution: Use the <strong
class="gj hi">STM32 Backup Registers</strong>. Blue Pills Backup Registers are ten 16-bit registers
that we may use to store 20 bytes of data. The contents of the registers will be preserved across
restarts and wakeups,<strong class="gj hi"> as long as there is Backup Power (or Main Power) supplied
to Blue Pill</strong>. It works just the Real Time Clock!</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/ebe183a495201248127da64f50a28e89.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/codal-libopencm3/blob/master/stm32/bootloader/stm32f103/backup.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/codal-libopencm3/blob/master/stm32/bootloader/stm32f103/backup.c</a>
</em></p></figcaption>
</div>
<p id="2fa6" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This code was used in my
Bootloader (from an earlier article) to remember whether Blue Pill is supposed to restart in
Bootloader Mode or Application Mode. Check out the article: <em class="hh"></em><a
class="at cg gv gw gx gy" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/stm32-blue-pill-bootloading-the-webusb-bootloader"><em
class="hh">STM32 Blue Pill — Bootloading the WebUSB Bootloader</em></a><em class="hh"></em></p>
</div>
</div>
</section>
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="d9e6" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Patch Mynewt
OS Functions</h1>
<p id="a0c9" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">The low power functions were
implemented in a custom library <code
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/low-power/libs/low_power" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">libs/low_power</a></code>.
How did we patch the Mynewt OS functions like <code class="dm ix iy iz ja b">os_task_idle()</code>
with our custom library? By using the Linker Wrap directive in our library…</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/bd50adde39904592f144d32e089329b7.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/pkg.yml"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/pkg.yml</a>
</em></p></figcaption>
</div>
<p id="696a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When the GNU Linker collates the
compiled object files (<code class="dm ix iy iz ja b">*.o</code>) to create the firmware image, it
will look for all calls to <code class="dm ix iy iz ja b">os_tick_idle()</code> and rename them as
calls to <code class="dm ix iy iz ja b">__wrap_os_tick_idle()</code>.</p>
<p id="b887" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that GNU Linker will NOT
rename the original <code class="dm ix iy iz ja b">os_tick_idle()</code> function defined in Mynewt.
Which means that we may implement the <code class="dm ix iy iz ja b">__wrap_os_tick_idle()</code>
function ourselves and the callers will happily pretend that its really <code
class="dm ix iy iz ja b">os_tick_idle()</code>. Thats how we intercept system functions in Mynewt…
</p>
<div class="figure gz ha hb hc hd cz">
<p><script src="https://gist.github.com/lupyuen/f6c7eb1dfd0728c2993f6044fa1e046b.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/hal_os_tick.c"
class="at cg gv gw gx gy" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/hal_os_tick.c</a>
</em></p></figcaption>
</div>
<p id="0293" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Its a nasty way to alter the
behaviour of Mynewt (and I dont condone it). But for exploratory and educational purposes, its
probably OK.</p>
<p id="737a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that the firmware size is
close to 60 KB. Adding the 4 KB Stub Bootloader we get total 64 KB of Flash ROM used. This is very
close to Blue Pills 64 KB ROM capacity. When youre not debugging, uncomment the <code
class="dm ix iy iz ja b">-Os</code> option in <code
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/apps/my_sensor_app/pkg.yml" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">apps/my_sensor_app/pkg.yml</a></code>
</p>
<pre
class="gz ha hb hc hd jh ji jj"><span id="824d" class="jk if ec bk ja b ds jl jm r jn"># C compiler flags<br/>pkg.cflags:<br/> - -DFLOAT_SUPPORT # For encoding floats in CoAP messages<br/># - -Os # Optimise for smallest size</span></pre>
<p id="1511" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Also the random number generator
has been disabled to reduce code size, hence the Device ID is always <code
class="dm ix iy iz ja b">0000…</code> To enable it, change <code
class="dm ix iy iz ja b">HMAC_PRNG</code> to <code class="dm ix iy iz ja b">1</code> in <code
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/targets/bluepill_my_sensor/syscfg.yml" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>
</p>
<pre
class="gz ha hb hc hd jh ji jj"><span id="017a" class="jk if ec bk ja b ds jl jm r jn">HMAC_PRNG: 0 # Disable HMAC PRNG pseudorandom number generator</span></pre>
</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:41:17 Dec 04, 2019 AND RETRIEVED FROM THE
INTERNET ARCHIVE ON 23:13:43 Feb 22, 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):
exclusion.robots: 0.378
LoadShardBlock: 300.664 (3)
PetaboxLoader3.resolve: 210.656
RedisCDXSource: 11.309
PetaboxLoader3.datanode: 171.345 (4)
CDXLines.iter: 31.052 (3)
captures_list: 348.182
exclusion.robots.policy: 0.362
esindex: 0.011
load_resource: 237.74
-->