lupyuen.org/articles/build-an-nb-iot-gps-tracker-on-stm32-l476-with-apache-mynewt-and-embedded-rust.html

1475 lines
No EOL
112 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/build-an-nb-iot-gps-tracker-on-stm32-l476-with-apache-mynewt-and-embedded-rust.html" />
<!-- End Wayback Rewrite JS Include -->
<title data-rh="true">Build an NB-IoT GPS Tracker on STM32 L476 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-09-22T12:24:41.202Z" />
<meta data-rh="true" name="title"
content="Build an NB-IoT GPS Tracker on STM32 L476 with Apache Mynewt and Embedded Rust" />
<meta data-rh="true" property="og:title"
content="Build an NB-IoT GPS Tracker on STM32 L476 with Apache Mynewt and Embedded Rust" />
<meta data-rh="true" property="twitter:title"
content="Build an NB-IoT GPS Tracker on STM32 L476 with Apache Mynewt and Embedded Rust" />
<meta data-rh="true" name="description"
content=" Lets build an NB-IoT GPS Tracker! A simple gadget that determines its current location based on received GPS signals… And transmits the location to a server via NB-IoT. We shall take an existing…" />
<meta data-rh="true" property="og:description"
content="Plus Quectel L70-R GPS, Quectel BC95 NB-IoT modules and thethings.io" />
<meta data-rh="true" property="twitter:description"
content="Plus Quectel L70-R GPS, Quectel BC95 NB-IoT modules and thethings.io" />
<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/q1.jpeg">
<!-- 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/q1.jpeg" /></p>
<figcaption><p><em>NB-IoT GPS Tracker running on the Ghostyu
NB-EK-L476 Developer Kit with STM32L476RCT6 microcontroller, Quectel L70-R GPS module and Quectel BC95
NB-IoT module. Photo taken during the field test at Berlayer Creek Boardwalk (and mangrove swamp) in
Singapore.</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<div>
<div id="5984" class="ea eb ec bk ed b ee ef eg eh ei ej ek">
<h1 class="ed b ee el ec">Build an NB-IoT GPS Tracker on STM32 L476 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/build-an-nb-iot-gps-tracker-on-stm32-l476-with-apache-mynewt-and-embedded-rust">
22 Sep 2019</a> <!-- -->·
<!-- -->
<!-- -->16
<!-- --> min read
</div>
</span></span>
</div>
</div>
</div>
</div>
</div>
<p id="c30e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="gv">Plus Quectel L70-R
GPS, Quectel BC95 NB-IoT modules and thethings.io</em></p>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q2.png" /></p>
<figcaption><p><em>The Completed NB-IoT GPS Tracker Application
showing geolocation and sensor data (raw temperature)</em></p></figcaption>
</div>
<p id="20b9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Lets build an <strong
class="gj hp">NB-IoT GPS Tracker</strong>! A simple gadget that determines its current location
based on received GPS signals… And transmits the location to a server via NB-IoT.</p>
<p id="bdb6" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We shall take an existing <a
href="https://mynewt.apache.org/"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Apache Mynewt Embedded OS</a> +
Embedded Rust project from the article <em class="gv"></em><a class="at cg hq hr hs ht"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt"><em
class="gv">Rust Rocks NB-IoT! STM32 Blue Pill with Quectel BC95-G on Apache Mynewt</em></a><em
class="gv"></em>… And extend it with a GPS module: <a
href="https://www.quectel.com/product/l70r.htm"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow"><strong class="gj hp">Quectel
L70-R</strong></a>.</p>
<p id="3c4a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The project already includes the
<a href="https://www.quectel.com/product/bc95.htm"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow"><strong class="gj hp">Quectel
BC95</strong></a> NB-IoT module for transmitting sensor data in CoAP format over NB-IoT.</p>
<p id="bc3b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">STM32 Blue Pill F103 doesnt
support floating-point computations in hardware, so it will be inefficient to compute floating-point
latitude/longitude coordinates for the GPS module.</p>
<p id="7cde" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Well upgrade the STM32 F103
microcontroller to an <a
href="https://www.st.com/en/microcontrollers-microprocessors/stm32l476rc.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow"><strong class="gj hp">STM32
L476</strong></a> because it supports floating-point computations in hardware.</p>
<p id="19d8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Thankfully theres already a
developer kit that contains the STM32 L476 microcontroller, Quectel L70-R GPS module and Quectel BC95
NB-IoT module… <a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/quick-peek-of-huawei-liteos-with-nb-iot-on-ghostyu-nb-ek-l476-developer-kit"><strong
class="gj hp">Ghostyu NB-EK-L476 Developer Kit</strong></a>, as described in the article <em
class="gv"></em><a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/quick-peek-of-huawei-liteos-with-nb-iot-on-ghostyu-nb-ek-l476-developer-kit"><em
class="gv">Quick Peek of Huawei LiteOS with NB-IoT on Ghostyu NB-EK-L476 Developer Kit
(STM32L476RCT6)</em></a><em class="gv">”. </em>Perfect for our NB-IoT GPS Tracker!</p>
<p id="58ca" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Alternatively we may create your
own kit based on the same STM32L476RCT6 microcontroller and Quectel modules.</p>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hu hv hw hx hn">
<p><script src="https://gist.github.com/lupyuen/43d550cda1ec4fc51a6de71f3b9cbce4.js"></script></p>
<figcaption><p><em>Upgrading from STM32 Blue Pill F103 to L476
</em></p></figcaption>
</div>
<p id="3ab3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="gv">How hard is it to
switch microcontrollers and migrate a Mynewt + Rust project from STM32 Blue Pill F103 to L476?</em>
As we shall find out… Not that hard!</p>
<p id="da6d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Below is the overall map of
changes made to the Mynewt + Rust project while building the NB-IoT GPS Tracker. Well study each
block in the subsequent sections.</p>
<p id="358b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="gv">Even if youre new
to Mynewt or Rust, feel free to skim this article!</em> While building the NB-IoT GPS Tracker we
made changes to a number of components in Mynewt OS and the Rust application… Youll soon understand
how the various parts of Mynewt and Rust work together to create an IoT gadget.</p>
</div>
</div>
<div class="cz ak">
<div class="figure gx gy gz ha hb cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q3.png" /></p>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="945d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The complete source code is
available at the <code class="dm ia ib ic id b">l476</code> branch of this repository…</p>
<div class="ie if ig ih ii ij"><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476?source=post_page-----8c095a925546----------------------"
rel="noopener nofollow">
<section class="im cl cm ak ce n ar in io ip iq ir is it iu iv iw ix iy iz ja jb">
<div class="jc n co p jd je">
<h2 class="bj jf jg bl ec">
<div class="di ik fe ff il fh">lupyuen/stm32bluepill-mynewt-sensor</div>
</h2>
</div>
<div class="jj r">
<div class="jk r jl jm jn jj jo jp jq"></div>
</div>
</section>
</a></div>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q4.png" /></p>
<figcaption><p><em>Changes made for Mynewt Board Support Package
</em></p></figcaption>
</div>
<h1 id="9d72" class="kc kd ec bk bj jf ke kf kg kh ki kj kk kl km kn ko">Mynewt Board Support Package
</h1>
<p id="689f" class="gh gi ec bk gj b gk kp gm kq go kr gq ks gs kt gu">Every Mynewt project begins with
a <a
href="https://mynewt.apache.org/latest/os/core_os/porting/port_bsp.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Board Support Package</a>… Either
take an existing one, or adapt from one. <a
href="https://github.com/apache/mynewt-core/tree/master/hw/bsp"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Check out the Board Support
Packages</a></p>
<p id="9491" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">A Board Support Package contains
information, scripts and drivers necessary to build Mynewt for our microcontroller and the associated
peripherals on our microcontroller board: flash memory, LEDs, UART ports, …</p>
<p id="3036" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">For this project, we customised
an existing Board Support Package <code
class="dm ia ib ic id b"><a href="https://github.com/apache/mynewt-core/tree/master/hw/bsp/nucleo-l476rg" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">nucleo-l476rg</a></code>
by copying into <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/hw/bsp/stm32l4" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">hw/bsp/stm32l4</a></code>
and renaming it. (<a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">The
previous project</a> used the Board Support Package <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/hw/bsp/bluepill-64kb" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">hw/bsp/bluepill-64kb</a></code>)
</p>
<p id="88d7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Our board is similar to the <a
href="https://www.st.com/en/evaluation-tools/nucleo-l476rg.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Nucleo L476RG</a>, except that the
Nucleo has 1 MB of flash ROM while ours has only 256 KB. Heres how we resized the flash ROM by
editing <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/hw/bsp/stm32l4/bsp.yml" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">hw/bsp/stm32l4/bsp.yml</a></code>
</p>
</div>
</div>
<div class="cz ak">
<div class="figure gx gy gz ha hb cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q5.png" /></p>
<figcaption><p><em>Customising a Board Support Package for STM32
L476 on Mynewt</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="7cbd" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Board Support Package for the
Nucleo defines two UART ports…</p>
<ul class="">
<li id="f73a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu kv kw kx">The first is named
<code class="dm ia ib ic id b">UART_0</code> which points to port <code
class="dm ia ib ic id b">USART2</code> (connected to the Quectel BC95 NB-IoT module)</li>
<li id="0eec" class="gh gi ec bk gj b gk ky gm kz go la gq lb gs lc gu kv kw kx">The second is named
<code class="dm ia ib ic id b">UART_1</code> which points to port <code
class="dm ia ib ic id b">USART1</code> (not used)</li>
</ul>
<p id="1ecf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="gv">(Yep dont confuse
the Mynewt port name with the actual UART port)</em></p>
<p id="485f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">For our board we need a third
port…</p>
<ul class="">
<li id="6f0b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu kv kw kx"><code
class="dm ia ib ic id b">UART_2</code> which points to port <code
class="dm ia ib ic id b">LPUART1</code> (connected to the Quectel L70-R GPS module)</li>
</ul>
<p id="1e86" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres how we add <code
class="dm ia ib ic id b">UART_2</code> by editing <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/hw/bsp/stm32l4/syscfg.yml" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">hw/bsp/stm32l4/syscfg.yml</a></code>
</p>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hu hv hw hx hn">
<p><script src="https://gist.github.com/lupyuen/747821c3cbde9175a479abcee8f05a91.js"></script></p>
<figcaption><p><em>Adding UART_2 to Board Support Package
Configuration. From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/hw/bsp/stm32l4/syscfg.yml"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/hw/bsp/stm32l4/syscfg.yml</a>
</em></p></figcaption>
</div>
<p id="38a3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But wait… This says that <code
class="dm ia ib ic id b">UART_2</code> will point to port <code
class="dm ia ib ic id b">USART3</code>, not <code class="dm ia ib ic id b">LPUART1</code>!</p>
<p id="45c5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Mynewt doesnt have the driver
code to support LPUARTs (Low Power UART) on the STM32 platform, so we used a quick hack…</p>
</div>
</div>
<div class="cz ak">
<div class="figure gx gy gz ha hb cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q6.png" /></p>
<figcaption><p><em>From STM32L476xx Datasheet <a
href="https://www.st.com/resource/en/datasheet/stm32l476je.pdf"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://www.st.com/resource/en/datasheet/stm32l476je.pdf</a> and Ghostyu
NB-EK-L476 Hardware Manual <a
href="https://drive.google.com/file/d/14KZqMO6cj20eKqM85iJNth8vf_WbI5VM/view?usp=sharing"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://drive.google.com/file/d/14KZqMO6cj20eKqM85iJNth8vf_WbI5VM/view?usp=sharing</a>
</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="0979" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <a
href="https://www.st.com/resource/en/datasheet/stm32l476je.pdf"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">STM32L476 Datasheet</a> says that
<code class="dm ia ib ic id b">LPUART1</code> and <code class="dm ia ib ic id b">USART3</code> share
the same <code class="dm ia ib ic id b">TX</code> and <code class="dm ia ib ic id b">RX</code> pins,
except that they are flipped. <em class="gv">(How odd!)</em> STM32 programs may configure the UART
port such that the <code class="dm ia ib ic id b">TX</code> and <code
class="dm ia ib ic id b">RX</code> pins are swapped… Thats how we disguised <code
class="dm ia ib ic id b">USART3</code> as <code class="dm ia ib ic id b">LPUART1</code>! More about
swapping <code class="dm ia ib ic id b">TX</code> and <code class="dm ia ib ic id b">RX</code> in a
while.</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/6c9c8f09f15ef145d06902cd1b2a451e.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/hw/bsp/stm32l4/src/hal_bsp.c"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/hw/bsp/stm32l4/src/hal_bsp.c</a>
</em></p></figcaption>
</div>
<p id="4ffd" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We complete the UART
customisation by adding the above code to <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/hw/bsp/stm32l4/src/hal_bsp.c" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">hw/bsp/stm32l4/src/hal_bsp.c</a></code>.
We are now ready to use our custom Board Support Package!</p>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q7.png" /></p>
<figcaption><p><em>Changes made for Mynewt Hardware Abstraction
Layer</em></p></figcaption>
</div>
<h1 id="b33a" class="kc kd ec bk bj jf ke kf kg kh ki kj kk kl km kn ko">Mynewt Hardware Abstraction
Layer</h1>
<p id="c541" class="gh gi ec bk gj b gk kp gm kq go kr gq ks gs kt gu">Lets talk about the Hardware
Abstraction Layer (HAL) in Mynewt… Because there are two definitions of HAL used in Mynewt that may
confuse us…</p>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q8.png" /></p>
<figcaption><p><em>General HAL for STM32 in
repos/apache-mynewt-core/hw/mcu/stm/stm32_common</em></p></figcaption>
</div>
<p id="69f4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1⃣ The first type of HAL is the
<strong class="gj hp">General HAL that abstracts all the hardware on our microcontroller.</strong> The
General HAL enables us to write Mynewt applications that are portable across microcontrollers. Heres
an example of a General HAL that <a
href="https://mynewt.apache.org/latest/os/modules/hal/hal_gpio/hal_gpio.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">abstracts the GPIO interface</a>:
<code
class="dm ia ib ic id b"><a href="https://mynewt.apache.org/latest/os/modules/hal/hal_gpio/hal_gpio.html" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">https://mynewt.apache.org/latest/os/modules/hal/hal_gpio/hal_gpio.html</a></code>
</p>
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
<div class="figure du cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q9.png" /></p>
<figcaption><p><em>Vendor-Specific HAL for STM32 in
repos/apache-mynewt-core/hw/mcu/stm/stm32l4xx</em></p></figcaption>
</div>
<p id="ac73" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2⃣ The second type of HAL is the
<strong class="gj hp">Vendor-Specific HAL provided by a microcontroller maker</strong> (like
STMicroelectronics) that abstracts the differences between various models of microcontrollers, e.g.
STM32 F103 vs L476. Heres a <a
href="https://github.com/apache/mynewt-core/tree/master/hw/mcu/stm/stm32l4xx/src/ext/Drivers/STM32L4xx_HAL_Driver/Src"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Vendor-Specific HAL</a>: <code
class="dm ia ib ic id b"><a href="https://github.com/apache/mynewt-core/tree/master/hw/mcu/stm/stm32l4xx/src/ext/Drivers/STM32L4xx_HAL_Driver/Src" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">https://github.com/apache/mynewt-core/tree/master/hw/mcu/stm/stm32l4xx/src/ext/Drivers/STM32L4xx_HAL_Driver/Src</a></code>
</p>
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
<p id="8171" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">From now on, when we mention
“HAL” we refer to 1<strong class="gj hp">General HAL</strong>.</p>
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q10.png" /></p>
<figcaption><p><em>From STM32L4x6 Reference Manual: <a
href="https://www.st.com/content/ccc/resource/technical/document/reference_manual/02/35/09/0c/4f/f7/40/03/DM00083560.pdf/files/DM00083560.pdf/jcr:content/translations/en.DM00083560.pdf"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://www.st.com/content/ccc/resource/technical/document/reference_manual/02/35/09/0c/4f/f7/40/03/DM00083560.pdf/files/DM00083560.pdf/jcr:content/translations/en.DM00083560.pdf</a>
</em></p></figcaption>
</div>
<p id="4650" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Recall that we need to patch the
UART HAL so that the <code class="dm ia ib ic id b">TX</code> and <code
class="dm ia ib ic id b">RX</code> pins are swapped for port <code
class="dm ia ib ic id b">USART3</code> (so that it behaves like <code
class="dm ia ib ic id b">LPUART1</code>). The <a
href="https://www.st.com/content/ccc/resource/technical/document/reference_manual/02/35/09/0c/4f/f7/40/03/DM00083560.pdf/files/DM00083560.pdf/jcr:content/translations/en.DM00083560.pdf"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">STM32L4x6 Reference Manual</a>
says that we may set the <code class="dm ia ib ic id b">SWAP</code> bit of UART register <code
class="dm ia ib ic id b">CR2</code> to swap the <code class="dm ia ib ic id b">TX/RX</code> pins.
</p>
<p id="6956" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The UART HAL for STM32 is
implemented in <code
class="dm ia ib ic id b"><a href="https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_uart.c" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">apache-mynewt-core/hw/mcu/stm/stm32_common/src/hal_uart.c</a></code>
(inside the <code class="dm ia ib ic id b">repos</code> folder of our project). Edit the file at line
468 to set the <code class="dm ia ib ic id b">SWAP</code> bit of <code
class="dm ia ib ic id b">CR2</code> like this…</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/99e2127572672e4ef3ebe932163e8125.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/patch/hal_uart.c#L468-L471"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/patch/hal_uart.c#L468-L471</a>
</em></p></figcaption>
</div>
<p id="460b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">You may refer to this <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/patch/hal_uart.c#L468-L471"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">patched version of </a><code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/patch/hal_uart.c#L468-L471" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">hal_uart.c</a></code>.
This patch depends on two conditions…</p>
<p id="ebb7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<code
class="dm ia ib ic id b">UART_2_SWAP_TXRX</code> must be set to 1 in the <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/syscfg.yml" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">syscfg.yml</a></code><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/syscfg.yml"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow"> configuration file</a>. Remember
that <code class="dm ia ib ic id b">UART_2</code> is the Mynewt name for port <code
class="dm ia ib ic id b">USART3</code>.</p>
<p id="3d79" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2⃣ UART port must be <code
class="dm ia ib ic id b">USART3</code></p>
<p id="8f80" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Where is <code
class="dm ia ib ic id b">USART_CR2_SWAP</code> defined? In the <a
href="https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32l4xx/src/ext/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Vendor-Specific HAL</a>.</p>
<p id="78e7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In Visual Studio Code, the patch
should look like this…</p>
</div>
</div>
<div class="cz ak">
<div class="figure gx gy gz ha hb cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q11.png" /></p>
<figcaption><p><em>Patching hal_uart.c to swap TX/RX pins for
USART3</em></p></figcaption>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="b3f1" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Mynewt Targets</h1>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q12.png" /></p>
<figcaption><p><em>Changes made for Mynewt Targets</em></p></figcaption>
</div>
<p id="6619" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Mynewt Applications are designed
to be portable across microcontrollers… The same application may be recompiled to run on STM32 Blue
Pill F103, STM32 F476, or even BBC micro:bit (based on Nordic nRF51).</p>
<p id="3977" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To compile a Mynewt Application
for a specific microcontroller board, we run the <code class="dm ia ib ic id b">newt target</code>
command like this…</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/1ccf7b9927b5256b9ae785a228cacddb.js"></script></p>
</div>
<p id="4cd2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This creates two targets <code
class="dm ia ib ic id b">stm32l4_boot</code> (for the bootloader) and <code
class="dm ia ib ic id b">stm32l4_my_sensor</code> (for the application)…</p>
<p id="ef7d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_boot/pkg.yml" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">stm32l4_boot</a></code>
is based on the Stub Bootloader located at <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/apps/boot_stub" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">apps/boot_stub</a></code>
</p>
<p id="2117" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/targets/stm32l4_my_sensor" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">stm32l4_my_sensor</a></code>
is based on our platform-indepedent Sensor Application located at <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/apps/my_sensor_app" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">apps/my_sensor_app</a></code>
(which will be merged with the Rust application during compilation)</p>
<p id="4c2b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Both targets <code
class="dm ia ib ic id b">stm32l4_boot</code> and <code
class="dm ia ib ic id b">stm32l4_my_sensor</code> point to the same Board Support Package for STM32
L476 (<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/hw/bsp/stm32l4" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">hw/bsp/stm32l4</a></code>),
so they will produce Bootloader and Application Firmware Images that will run on our STM32 L476 board.
</p>
<p id="8484" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">(<a class="at cg hq hr hs ht"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">The
previous project</a> used targets <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/targets/bluepill_boot" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">bluepill_boot</a></code>
and <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/targets/bluepill_my_sensor" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">bluepill_my_sensor</a></code>)
</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="lw lx ly lz ma mb ag mc ah md aj ak">
<div class="figure gx gy gz ha hb cz mf mg paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q13.png" /></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_boot/target.yml"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_boot/target.yml</a>
and <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/target.yml"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/target.yml</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="2cd8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Instead of running the <code
class="dm ia ib ic id b">newt target</code> command to create the targets, we may copy the target
folders ourselves to create the targets. Be sure to update <code
class="dm ia ib ic id b">target.yml</code> to point to the correct Board Support Package (see
above).</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="lw lx ly lz ma mb ag mc ah md aj ak">
<div class="figure gx gy gz ha hb cz mf mg paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q14.png" /></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_boot/pkg.yml"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_boot/pkg.yml</a>
and <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/pkg.yml"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/pkg.yml</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="5d5d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The package name <code
class="dm ia ib ic id b">pkg.name</code> in <code class="dm ia ib ic id b">pkg.yml</code> should be
updated. C Compiler Directives and Linker Directives should be specified in <code
class="dm ia ib ic id b">pkg.yml</code>, as shown above.</p>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q15.png" /></p>
<figcaption><p><em>Changes made for Mynewt Libraries</em></p></figcaption>
</div>
<h1 id="6c06" class="kc kd ec bk bj jf ke kf kg kh ki kj kk kl km kn ko">Mynewt Libraries</h1>
<p id="e85c" class="gh gi ec bk gj b gk kp gm kq go kr gq ks gs kt gu">Lets look at the changes made to
the Mynewt libraries and drivers (located in <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">libs</a></code>)
that are used by our NB-IoT GPS Tracker application. Recall that <a class="at cg hq hr hs ht"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">the
previous project</a> has already provided libraries for transmitting sensor data in CoAP format over
NB-IoT, also for reading the STM32 internal temperature sensor.</p>
<p id="9f25" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/gps_l70r" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">gps_l70r</a></code>:
Driver for the Quectel L70-R GPS module. This is a new driver that connects to the UART port to
receive geolocation information (latitude, longitude, altitude) from the GPS module. It calls <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/tiny_gps_plus" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">tiny_gps_plus</a></code>
to parse the <a
href="https://en.wikipedia.org/wiki/NMEA_0183"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">NMEA</a> messages generated by the
GPS module.</p>
<p id="a55e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/tiny_gps_plus" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">tiny_gps_plus</a></code>:
<a href="http://arduiniana.org/libraries/tinygpsplus/"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">TinyGPS++</a> library that was
ported from Arduino. It parses NMEA messages generated by the GPS module to obtain geolocation
information.</p>
<p id="9c52" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/custom_sensor" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">custom_sensor</a></code>:
We added a custom Sensor Data Type for the GPS geolocation, which contains latitude, longitude and
altitude. This enables the <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/gps_l70r" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">gps_l70r</a></code>
GPS driver to be polled like any other sensor (e.g. internal temperature sensor) via <a
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_framework.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Mynewts Sensor Framework</a>.</p>
<p id="438e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">4<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/mynewt_rust" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">mynewt_rust</a></code>:
Helper functions were added to allow the Rust application to read the new Geolocation Sensor Data Type
</p>
<p id="d5b3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">5<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/buffered_serial" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">buffered_serial</a></code>:
Library that buffers data from the UART port for easier parsing. Used by the GPS driver <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/gps_l70r" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">gps_l70r</a></code>
and the Quectel NB-IoT driver <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/bc95g" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">bc95g</a></code>
</p>
<p id="467d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">6<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/adc_stm32l4" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">adc_stm32l4</a></code>:
We added this driver to support the Analog-To-Digital Converter (ADC) found in the STM32 L476
microcontroller. The ADC driver is used by the internal temperature sensor <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/temp_stm32" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">temp_stm32</a></code>
</p>
<p id="e3e3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">7<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/temp_stm32" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">temp_stm32</a></code>:
This is the driver for the internal temperature sensor. The driver has been updated to use <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/adc_stm32l4" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">adc_stm32l4</a></code>
to read the internal temperature sensor on the STM32 L476 microcontroller.</p>
<p id="ea30" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">With these updates, our Rust
application shall be able to <strong class="gj hp">poll the GPS sensor</strong> for the geolocation,
<strong class="gj hp">attach the geolocation</strong> to the internal temperature sensor data, and
<strong class="gj hp">transmit the geolocated sensor data</strong> to the CoAP Server at thethings.io
over NB-IoT.</p>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="4e38" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Application Configuration</h1>
<p id="a93b" class="gh gi ec bk gj b gk kp gm kq go kr gq ks gs kt gu">Where do we configure the
settings for the libraries? In the System Configuration File for our Target Application <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/syscfg.yml" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">targets/stm32l4_my_sensor/syscfg.yml</a></code>
</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/b5a8b097532a3d083c2119a5fbf40303.js"></script></p>
<figcaption><p><em>Application Configuration. From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/syscfg.yml"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/syscfg.yml</a>
</em></p></figcaption>
</div>
<p id="c935" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">(The System Configuration File
for <a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">the
previous project</a> was at <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/bluepill_my_sensor/syscfg.yml" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>)
</p>
<p id="ec7f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here we enable the drivers for
the GPS and NB-IoT modules, by setting <code class="dm ia ib ic id b">GPS_L70R</code> and <code
class="dm ia ib ic id b">BC95G</code> to <code class="dm ia ib ic id b">1</code>. We specify the
UART port for the GPS and NB-IoT modules like this…</p>
<pre
class="gx gy gz ha hb mk ml mm"><span id="38f7" class="mn kd ec bk id b ds mo mp r mq">GPS_L70R_UART: 0 # Connect to Quectel L70R module on USART2<br/>BC95G_UART: 2 # Connect to Quectel BC95-G module on LPUART1 <br/> # i.e. USART3 with TX/RX pins swapped</span></pre>
<p id="18b2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Why <code
class="dm ia ib ic id b">0</code> and <code class="dm ia ib ic id b">2</code>? Because the Mynewt
UART ports are named like this…</p>
<pre
class="gx gy gz ha hb mk ml mm"><span id="1638" class="mn kd ec bk id b ds mo mp r mq"><strong class="id hp">UART_0 → USART2</strong><br/>UART_1 → USART1<br/><strong class="id hp">UART_2 → USART3</strong></span></pre>
<p id="2b96" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Recall that we need to swap the
<code class="dm ia ib ic id b">TX/RX</code> pins for port <code class="dm ia ib ic id b">USART3</code>
so that it behaves like <code class="dm ia ib ic id b">LPUART1</code>. We have applied a patch in
<code class="dm ia ib ic id b">hal_uart.c</code> that swaps the pins only if <code
class="dm ia ib ic id b">UART_2_SWAP_TXRX</code> is set to <code class="dm ia ib ic id b">1</code>
</p>
<pre
class="gx gy gz ha hb mk ml mm"><span id="9da6" class="mn kd ec bk id b ds mo mp r mq"># Swap TX/RX pins for USART3 so that USART3 behaves like LPUART1<br/>UART_2_SWAP_TXRX: 1</span></pre>
<p id="e213" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">On the Ghostyu developer kit, the
GPS module is disabled by default. The GPS driver needs to set Pin PA1 to high to enable the GPS
module. We specify the pin like this…</p>
<pre
class="gx gy gz ha hb mk ml mm"><span id="2bcd" class="mn kd ec bk id b ds mo mp r mq"># GPIO Pin PA1 enables and disables the GPS module<br/>GPS_L70R_ENABLE_PIN: MCU_GPIO_PORTA(1)</span></pre>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="8fd9" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Rust Application</h1>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q16.png" /></p>
<figcaption><p><em>Changes made for Rust Application</em></p></figcaption>
</div>
<p id="3bd5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><a class="at cg hq hr hs ht"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">In
the previous project</a> we have created an Embedded Rust application that polls the internal
temperature sensor every 10 seconds and transmits the temperature to the CoAP server (at
thethings.io). Now well extend the Rust application to transmit the GPS Geolocation (latitude,
longitude) together with the temperature.</p>
<p id="c4e8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We reused the Rust modules in
<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/rust/app/src" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">rust/app/src</a></code>
from the previous application…</p>
<p id="cc5f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/lib.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">lib.rs</a></code>:
Main program that starts the sensors and networking</p>
<p id="b0c4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_sensor.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">app_sensor.rs</a></code>:
Poll the internal temperature sensor <code class="dm ia ib ic id b">temp_stm32</code> and call <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_network.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">app_network.rs</a></code>
to transmit the data</p>
<p id="b565" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_network.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">app_network.rs</a></code>:
Compose a CoAP Message with a JSON Payload to transmit the temperature data to the CoAP server at
thethings.io</p>
<p id="bca8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We added a new module <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/gps_sensor.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">gps_sensor.rs</a></code>
that instructs Mynewt to poll our GPS sensor every 11 seconds. This is possible because our GPS driver
<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/gps_l70r" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">gps_l70r</a></code>
has been integrated with <a
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_framework.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Mynewts Sensor Framework</a> so
that it works like any other sensor (such as the internal temperature sensor).</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/97a2f74eaada70f55933d44290f93e6b.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/gps_sensor.rs"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/gps_sensor.rs</a>
</em></p></figcaption>
</div>
<p id="2773" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Now we have two sources of sensor
data in our Rust application…</p>
<p id="c413" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<strong
class="gj hp">Internal Temperature Sensor Data</strong>, generated by the <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/temp_stm32" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">temp_stm32</a></code>
driver</p>
<p id="1ba8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<strong class="gj hp">GPS
Geolocation (latitude, longitude, altitude)</strong>, generated by the <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/libs/gps_l70r" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">gps_l70r</a></code>
driver</p>
<p id="0b38" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To conserve NB-IoT packets, well
aggregate the two types of sensor data and transmit as a single CoAP message. Thats why the Sensor
Listeners for both sensors have been updated to forward the polled sensor data to a new function <code
class="dm ia ib ic id b">aggregate_sensor_data()</code> defined in <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_network.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">app_network.rs</a></code>
</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/aae88e535fb9e7293cbde052e0134513.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_network.rs"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_network.rs</a>
</em></p></figcaption>
</div>
<p id="4a6e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When <code
class="dm ia ib ic id b">aggregate_sensor_data()</code> receives a GPS Geolocation, it doesnt
transmit the data to the server. Instead it stores the GPS Geolocation.</p>
<p id="4d32" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When <code
class="dm ia ib ic id b">aggregate_sensor_data()</code> receives the temperature sensor data, it
attaches the stored GPS Geolocation to the sensor data, and transmits the geolocated sensor data like
this…</p>
<pre
class="gx gy gz ha hb mk ml mm"><span id="8438" class="mn kd ec bk id b ds mo mp r mq">{ &quot;values&quot;: [<br/> { &quot;key&quot; : &quot;t&quot;, <br/> &quot;value&quot;: 960, <br/> &quot;geo&quot; : { &quot;lat&quot;: 1.2701, &quot;long&quot;: 103.8078 }}<br/> ...<br/>]}</span></pre>
<p id="7287" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This <a
href="https://developers.thethings.io/docs/json-1"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">JSON Payload format</a> is
specified by thethings.io for transmitting sensor data (<code
class="dm ia ib ic id b">temperature t = 960</code>) with attached geolocation (<code
class="dm ia ib ic id b">latitude = 1.2701, longitude = 103.8078</code>).</p>
<p id="b9ef" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Rust code for creating the
JSON Payload is exactly the same as before, based on the <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/mynewt/src/encoding/macros.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">coap!</a></code>
macro…</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/de7c3586c823f16abe195456a72f7198.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_network.rs"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/</a>
</em></p></figcaption>
</div>
<div class="figure du cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q17.png" /></p>
<figcaption><p><em>Geolocated Sensor Data rendered in a dashboard
at thethings.io</em></p></figcaption>
</div>
<p id="81b5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">How is this possible? Because the
<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/mynewt/src/encoding/macros.rs" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">coap!</a></code>
macro has been updated to <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/mynewt/src/encoding/macros.rs#L535-L536"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">emit the GPS Geolocation</a>
attached to the sensor data in <code class="dm ia ib ic id b">val</code> (if the GPS Geolocation
exists).</p>
<p id="d174" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The screen shows how the
Geolocated Sensor Data transmitted by our device would be rendered in a dashboard at thethings.io.</p>
<p id="3ef0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Thats the power of creating a
Domain-Specific Language (like <code class="dm ia ib ic id b">coap!</code>) in Rust… We simply focus
on the intent of transmitting sensor data, and let the macro decide how to generate the right payload
to match our intent.</p>
<p id="38a7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">One more enhancement implemented
in the Mynewt Rust Wrapper: The polling of Mynewt sensors in the Rust application has been made
simpler by introducing <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/mynewt/src/hw/sensor_mgr.rs"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Rust Iterators</a></p>
</div>
</div>
<div class="cz ak">
<div class="figure gx gy gz ha hb cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q18.png" /></p>
<figcaption><p><em>Rust Iterators for polling Mynewt sensors. From
<a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_sensor.rs"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/rust/app/src/app_sensor.rs</a>
</em></p></figcaption>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="4d93" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Mynewt Build and Flash Scripts
</h1>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q19.png" /></p>
<figcaption><p><em>Changes made for Mynewt Build and Flash
Scripts</em></p></figcaption>
</div>
<p id="9523" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Mynewt provides the <a
href="https://mynewt.apache.org/latest/newt/newt_ops.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">command-line tool </a><code
class="dm ia ib ic id b"><a href="https://mynewt.apache.org/latest/newt/newt_ops.html" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">newt</a></code>
for building the firmware image and flashing it to the microcontroller. On Windows, <code
class="dm ia ib ic id b">newt</code> requires the <a
href="https://mynewt.apache.org/latest/newt/newt_ops.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">MSYS2 and MinGW toolchains to be
installed</a>.</p>
<p id="87a2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">I wanted to simplify the
installation of the Mynewt build tools on Windows (and make them more robust), so I chose to write my
own build and flash scripts based on pure Windows, without MSYS2 and MinGW. Earlier I have
experimented with <code class="dm ia ib ic id b">newt</code> on <a
href="https://docs.microsoft.com/en-us/windows/wsl/about"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Windows Subsystem for Linux</a>
but the performance was awful so I dropped it.</p>
<p id="ce30" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The custom build scripts for
STM32 L476 are located in the <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/scripts/stm32l4" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">scripts/stm32l4</a></code>
folder (except for <code class="dm ia ib ic id b">build-app</code>, which is located in <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/scripts" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">scripts</a></code>).
The <code class="dm ia ib ic id b">*.cmd</code> scripts are for Windows, <code
class="dm ia ib ic id b">*.sh</code> scripts are for macOS and Linux (though not extensively tested
for Linux). <code class="dm ia ib ic id b">*.ocd</code> are the <a
href="http://openocd.org/doc-release/html/About.html#About"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">OpenOCD</a> scripts for flashing
and debugging (they control the ST-Link interface).</p>
<p id="5b4e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/build-boot.cmd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">build-boot.cmd</a>, <a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/build-boot.sh" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.sh</a></code>:
Build the bootloader by running <code class="dm ia ib ic id b">newt build stm32l4_boot</code></p>
<p id="994d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/build-app.cmd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">build-app.cmd</a>, <a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/build-app.sh" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.sh</a></code>:
Build the application by running <code class="dm ia ib ic id b">newt build stm32l4_my_sensor</code>.
Also builds the Rust application and injects the compiled Rust code into the build.</p>
<p id="6531" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Previously the Rust build for
STM32 Blue Pill F103 was targeted for <code class="dm ia ib ic id b">thumbv7m-none-eabi</code> (Arm
Cortex M3), now the Rust build for STM32 L476 is targeted for <code
class="dm ia ib ic id b">thumbv7em-none-eabihf</code> (Arm Cortex M4 with Hardware Floating-Point)
</p>
<p id="9e8e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/image-app.cmd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">image-app.cmd</a>, <a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/image-app.sh" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.sh</a></code>:
Create the application firmware image: <code
class="dm ia ib ic id b">newt create-image -v stm32l4_my_sensor 1.0.0</code></p>
<p id="54cf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">4<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/flash-boot.cmd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">flash-boot.cmd</a>, <a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/flash-boot.sh" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.sh</a></code>:
Flash the bootloader with OpenOCD</p>
<p id="e032" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">5<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/flash-boot.ocd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">flash-boot.ocd</a></code>:
OpenOCD script for flashing the bootloader</p>
<p id="a8b9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">6<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/flash-app.cmd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">flash-app.cmd</a>, <a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/flash-app.sh" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.sh</a></code>:
Flash the application with OpenOCD</p>
<p id="70cc" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">7<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/flash-app.ocd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">flash-app.ocd</a></code>:
OpenOCD script for flashing the application</p>
<p id="8778" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">8<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/flash-init.ocd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">flash-init.ocd</a></code>:
OpenOCD initialisation script called by <code class="dm ia ib ic id b">flash-boot.ocd</code> and <code
class="dm ia ib ic id b">flash-app.ocd</code></p>
<p id="6b74" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">9<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/scripts/stm32l4/debug.ocd" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">debug.ocd</a></code>:
OpenOCD script for debugging the application. Called by the <a
href="https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Cortex-Debug Extension</a> in
<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch-stm32l4.json" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.vscode/launch-stm32l4.json</a></code>
</p>
<p id="3c78" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <code
class="dm ia ib ic id b">newt</code> command in the Windows scripts refer to the <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/newt"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Windows build of </a><code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/newt" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">newt</a></code>,
which works without MSYS2 and MinGW.</p>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q20.png" /></p>
<figcaption><p><em>Visual Studio Code Tasks in the Task Runner
</em></p></figcaption>
</div>
<p id="a466" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The above scripts are linked into
<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/tasks.json" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.vscode/tasks.json</a></code>
so that they will appear as Tasks in Visual Studio Code.</p>
<p id="c30c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">If were using the <a
href="https://marketplace.visualstudio.com/items?itemName=SanaAjani.taskrunnercode"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Task Runner Extension</a>, the
tasks will appear like this.</p>
<p id="0978" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">(The custom build and flash
scripts from <a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">the
previous project</a> are located in the <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/l476/scripts" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">scripts</a></code>
folder)</p>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="b94d" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Visual Studio Code
Configuration</h1>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q21.png" /></p>
<figcaption><p><em>Changes made for Visual Studio Code
Configuration</em></p></figcaption>
</div>
<p id="e969" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><a
href="https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Cortex-Debug</a> is the debugger
were using in Visual Studio Code to debug our application. We added a new debugger configuration
<code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch-stm32l4.json" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.vscode/launch-stm32l4.json</a></code>
for STM32 L476.</p>
<p id="e7b3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The debugger configuration
specifies the <a
href="http://openocd.org/doc-release/html/About.html#About"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">OpenOCD</a> scripts and <a
href="https://www.gnu.org/software/gdb/"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">GDB</a> commands for debugging the
application. Note that <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch.json" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">launch.json</a></code>,
the current debugger configuration, is overwritten by <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch-stm32l4.json" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">launch-stm32l4.json</a></code>
whenever the application is rebuilt. So we should never edit <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch.json" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">launch.json</a></code>.
</p>
<div class="figure gx gy gz ha hb cz">
<p><script src="https://gist.github.com/lupyuen/923a4ebab9f6592ed963ac249e6e621d.js"></script></p>
<figcaption><p><em>Cortex-Debug Configuration. From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch-stm32l4.json"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch-stm32l4.json</a>
</em></p></figcaption>
</div>
<p id="a63e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">(The debugger configuration from
<a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">the
previous project</a> is at <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/.vscode/launch-bluepill.json" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">.vscode/launch-bluepill.json</a></code>)
</p>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="8249" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Connect the Hardware</h1>
<p id="81ea" class="gh gi ec bk gj b gk kp gm kq go kr gq ks gs kt gu">To build the NB-IoT GPS Tracker
well need the following hardware…</p>
<p id="7b4e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1<a class="at cg hq hr hs ht"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/quick-peek-of-huawei-liteos-with-nb-iot-on-ghostyu-nb-ek-l476-developer-kit"><strong
class="gj hp">Ghostyu NB-EK-L476 Developer Kit</strong></a>, as described in the article <em
class="gv"></em><a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/quick-peek-of-huawei-liteos-with-nb-iot-on-ghostyu-nb-ek-l476-developer-kit"><em
class="gv">Quick Peek of Huawei LiteOS with NB-IoT on Ghostyu NB-EK-L476 Developer Kit
(STM32L476RCT6)</em></a><em class="gv"></em></p>
<p id="b286" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The kit includes the <a
href="https://www.st.com/en/microcontrollers-microprocessors/stm32l476rc.html"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">STM32L476RCT6</a> microcontroller,
<a href="https://www.quectel.com/product/bc95.htm"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Quectel BC95</a> NB-IoT module
(with antenna) and <a
href="https://www.quectel.com/product/l70r.htm"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Quectel L70-R</a> GPS module (with
antenna).</p>
<p id="72aa" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong
class="gj hp">Alternatively</strong>: You may assemble your own kit based on the same STM32
microcontroller and Quectel modules.</p>
<p id="a0b2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Remember to select a Quectel
NB-IoT module that works with your local NB-IoT Frequency Band. You may consider this <a
href="https://www.aliexpress.com/wholesale?catId=0&amp;initiative_id=SB_20190725022150&amp;SearchText=bc95-g+nb101&amp;switch_new_app=y"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow"><strong class="gj hp">Quectel
BC95-G Global NB-IoT Module</strong></a> (breakout board with antenna), which supports all global
bands.</p>
<p id="5bea" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To connect the components in your
custom kit, refer to the <a
href="https://drive.google.com/file/d/14KZqMO6cj20eKqM85iJNth8vf_WbI5VM/view?usp=sharing"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Ghostyu NB-EK-L476 schematics</a>.
Note that the Quectel NB-IoT module may require additional power, like <a
href="https://www.linkedin.com/posts/lupyuen_quectel-nbiot-stm32-activity-6558362381049790464-rDgF"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">tapping the 5V pin from
ST-Link</a> instead of sharing the ST-Links 3.3V pin with the microcontroller.</p>
<p id="4ba1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2<a
href="https://www.aliexpress.com/wholesale?catId=0&amp;initiative_id=SB_20180924134644&amp;SearchText=st-link+v2"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow"><strong class="gj hp">ST-Link V2
USB Adapter</strong></a><strong class="gj hp">: </strong>Under $2, search <a
href="https://www.aliexpress.com/wholesale?catId=0&amp;initiative_id=SB_20180924134644&amp;SearchText=st-link+v2&amp;switch_new_app=y"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">AliExpress</a> for <code
class="dm ia ib ic id b">st-link v2</code></p>
<p id="c2cb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3<strong class="gj hp">NB-IoT
SIM</strong> from your local NB-IoT network operator. <em class="gv">Many thanks to </em><a
href="https://www.starhub.com/" class="at cg hq hr hs ht"
target="_blank" rel="noopener nofollow"><strong class="gj hp"><em
class="gv">StarHub</em></strong></a><em class="gv"> for sponsoring the NB-IoT SIM that I used
for this tutorial!</em></p>
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q22.jpeg" /></p>
<figcaption><p><em>Pins connected from the SWD Debug Port to
ST-Link: SWDIO, SWCLK, VCC, GND</em></p></figcaption>
</div>
<div class="figure du cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q23.png" /></p>
<figcaption><p><em>SWD Debug Port on Ghostyu NB-EK-L476
</em></p></figcaption>
</div>
<p id="d88e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Connect the following pins from
the SWD Debug Port to ST-Link: <code class="dm ia ib ic id b">SWDIO</code>, <code
class="dm ia ib ic id b">SWCLK</code>, <code class="dm ia ib ic id b">VCC</code>, <code
class="dm ia ib ic id b">GND</code>.</p>
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q24.jpeg" /></p>
<figcaption><p><em>Ghostyu STM32 L476 Development Kit powered by
both ST-Link and micro-USB port. At top left is a USB hub.</em></p></figcaption>
</div>
<p id="c713" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">For the Ghostyu NB-EK-L476, you
need to <strong class="gj hp">connect the micro-USB port on the board to another USB port</strong> on
your computer. This means that the board will have two power sources: 3.3V power from ST-Link, and 5V
power from micro-USB port. This ensures that the NB-IoT module will have sufficient power.</p>
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q25.png" /></p>
<figcaption><p><em>NB-IoT Module Power Supply for Ghostyu
NB-EK-L476. From <a
href="https://drive.google.com/file/d/14KZqMO6cj20eKqM85iJNth8vf_WbI5VM/view?usp=sharing"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://drive.google.com/file/d/14KZqMO6cj20eKqM85iJNth8vf_WbI5VM/view?usp=sharing</a>
</em></p></figcaption>
</div>
<div class="figure du cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q26.png" /></p>
<figcaption><p><em>SIM partially exposed to show the unusual
orientation</em></p></figcaption>
</div>
<p id="176a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hp">Insert the
NB-IoT SIM</strong> into the Quectel NB-IoT Breakout Board according to the orientation shown in the
photo. (Yes the SIM notch faces outward, not inward)</p>
<p id="e9f5" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hp"><em
class="gv">Remember: Always connect the antenna before powering up the NB-IoT
module!</em></strong></p>
<p id="caaf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hp">If youre
using Windows: </strong>Make sure that the ST-Link Driver has been installed before connecting
ST-Link to your computer</p>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="d5e7" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Install and Run the NB-IoT GPS
Tracker</h1>
<p id="9bef" class="gh gi ec bk gj b gk kp gm kq go kr gq ks gs kt gu"><a class="at cg hq hr hs ht"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/install-apache-mynewt-and-embedded-rust-for-stm32-l476-and-visual-studio-code-on-windows">Follow
the instructions in this article</a> to install, build and run our application on the STM32 L476
development board (or equivalent).</p>
<p id="cb4f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">While running the application,
the Console Log should look like this…</p>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hu hv hw hx hn">
<p><script src="https://gist.github.com/lupyuen/47f000f1e67a6356333180439903286e.js"></script></p>
<figcaption><p><em>Adapter Output Log from <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/logs/standalone-node.log"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/logs/standalone-node.log</a>
</em></p></figcaption>
</div>
<p id="27c9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here you can see the program
reading the internal temperature sensor.</p>
<p id="1050" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The temperature sensor data is
combined with the GPS geolocation into a JSON Payload.</p>
<p id="61d0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The JSON Payload is then
transmitted as a CoAP Message to the CoAP server at thethings.io.</p>
<p id="7d55" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In the Console Log, there is a
URL displayed: <code class="dm ia ib ic id b">http://blue-pill-geolocate.appspot.com/...</code></p>
<p id="d9c0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Clicking this URL opens a web
page that displays the computed temperature (in degrees Celsius) and the GPS geolocation, based on the
sensor data received by thethings.io from your device over NB-IoT. This URL is randomly-generated each
time we restart our device.</p>
<p id="ad62" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We have installed a <a
href="https://github.com/lupyuen/thethingsio-wifi-geolocation"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">script at thethings.io</a> that
pushes the computed temperature and geolocation to <code
class="dm ia ib ic id b">blue-pill-geolocate.appspot.com</code>. For more details, check the section
<em class="gv">“Advanced Topic: WiFi Geolocation with thethings.io and Google App Engine”</em> in the
article <em class="gv"></em><a class="at cg hq hr hs ht" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/connect-stm32-blue-pill-to-esp8266-with-apache-mynewt"><em
class="gv">Connect STM32 Blue Pill to ESP8266 with Apache Mynewt</em></a><em class="gv"></em>.
</p>
<div class="figure gx gy gz ha hb cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q27.png" /></p>
<figcaption><p><em>Computed temperature and the GPS geolocation
</em></p></figcaption>
</div>
<p id="d921" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="gv">Does the
transmission of geolocation work when the device is on the move (say, when mounted on a vehicle?) If
the device moves between NB-IoT cells, will the transmission still succeed?</em></p>
<p id="fb06" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Yes! I have tested the NB-IoT GPS
Tracker while walking around… Geolocation updates are indeed transmitted correctly to thethings.io as
I walk.</p>
</div>
</div>
<div class="cz ak">
<div class="figure gx gy gz ha hb cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q28.jpeg" /></p>
<figcaption><p><em>Field testing of the NB-IoT GPS Tracker
</em></p></figcaption>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="bd64" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres a video demo of the NB-IoT
GPS Tracker…</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="lw lx ly lz ma mb ag mc ah md aj ak">
<div class="figure gx gy gz ha hb cz">
<div class="dl r dd">
<div class="nn r"><iframe
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FBLfAq1FzUbs%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DBLfAq1FzUbs&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FBLfAq1FzUbs%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
allowfullscreen="" frameborder="0" height="300" width="400"
title="Reading a Quectel GPS and transmitting over NB-IoT with Rust (3D Map)"
class="cp t u dh ak" scrolling="auto"></iframe></div>
</div>
</div>
</div>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="01c5" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">thethings.io Configuration</h1>
<p id="f1df" class="gh gi ec bk gj b gk kp gm kq go kr gq ks gs kt gu">If youre happy to view the
sensor data using my server at <code class="dm ia ib ic id b">blue-pill-geolocate.appspot.com</code>,
you may skip this section. If you wish to configure your own account for thethings.io, read on…</p>
<p id="c423" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Follow the steps in the three
videos below to configure your thethings.io account and install the Cloud Code Scripts. Click <code
class="dm ia ib ic id b">CC</code> to view the instructions.</p>
<p id="1e4e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong
class="gj hp">Note</strong>: There is one additional Cloud Code Function to be installed: <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/thethingsio-wifi-geolocation/blob/master/push_sensor_data.js" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">push_sensor_data</a></code>.
Copy the code <a
href="https://github.com/lupyuen/thethingsio-wifi-geolocation/blob/master/push_sensor_data.js"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">from this link</a> to create a new
Cloud Code Function named <code class="dm ia ib ic id b">push_sensor_data</code>.</p>
<p id="b211" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Thing Token should be updated
in the <code class="dm ia ib ic id b">COAP_URI</code> setting of the System Configuration File <code
class="dm ia ib ic id b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/targets/stm32l4_my_sensor/syscfg.yml" class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">targets/stm32l4_my_sensor/syscfg.yml</a></code>
</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="lw lx ly lz ma mb ag mc ah md aj ak">
<div class="figure gx gy gz ha hb cz">
<div class="dl r dd">
<div class="nn r"><iframe
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F4KJiZMboaUg%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D4KJiZMboaUg&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F4KJiZMboaUg%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
allowfullscreen="" frameborder="0" height="300" width="400"
title="Transform sensor data with thethings.io (Part 1 of 3)" class="cp t u dh ak"
scrolling="auto"></iframe></div>
</div>
<figcaption><p><em>thethings.io Configuration: Part 1 of 3.
Click CC to view the instructions.</em></p></figcaption>
</div>
<div class="figure da cz">
<div class="dl r dd">
<div class="nn r"><iframe
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FszCHheKEC7I%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DszCHheKEC7I&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FszCHheKEC7I%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
allowfullscreen="" frameborder="0" height="300" width="400"
title="Transform sensor data with thethings.io (Part 2 of 3)" class="cp t u dh ak"
scrolling="auto"></iframe></div>
</div>
<figcaption><p><em>thethings.io Configuration: Part 2 of 3.
Click CC to view the instructions.</em></p></figcaption>
</div>
<div class="figure da cz">
<div class="dl r dd">
<div class="nn r"><iframe
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FdMelHn4xTcM%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdMelHn4xTcM&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FdMelHn4xTcM%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
allowfullscreen="" frameborder="0" height="300" width="400"
title="Transform sensor data with thethings.io (Part 3 of 3)" class="cp t u dh ak"
scrolling="auto"></iframe></div>
</div>
<figcaption><p><em>thethings.io Configuration: Part 3 of 3.
Click CC to view the instructions.</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="68d4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">At the dashboard page, create a
new Widget with the following settings…</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="lw lx ly lz ma mb ag mc ah md aj ak">
<div class="gx gy gz ha hb n et">
<div class="figure da cz no np mg mf nq paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q29.png" /></p>
</div>
<div class="figure da cz ns np mg mf nq paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q30.png" /></p>
</div>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="dc11" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The geolocated temperature will
be shown in the Widget. Heres how it looks…</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="lw lx ly lz ma mb ag mc ah md aj ak">
<div class="figure gx gy gz ha hb cz mf mg paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q31.png" /></p>
<figcaption><p><em>thethings.io dashboard with geolocated
temperature sensor data</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<p id="468b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Heres a video demo of
thethings.io dashboard with geolocated temperature sensor data…</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="lw lx ly lz ma mb ag mc ah md aj ak">
<div class="figure gx gy gz ha hb cz">
<div class="dl r dd">
<div class="nn r"><iframe
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F2-CWQju-Ffs%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D2-CWQju-Ffs&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F2-CWQju-Ffs%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
allowfullscreen="" frameborder="0" height="300" width="400"
title="Reading a Quectel GPS and transmitting over NB-IoT with Rust" class="cp t u dh ak"
scrolling="auto"></iframe></div>
</div>
<figcaption><p><em>Video demo of thethings.io dashboard with
geolocated temperature sensor data</em></p></figcaption>
</div>
</div>
</div>
</div>
</section>
<hr class="jr dy js jt ju dv jv jw jx jy jz" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah dz aj ak">
<h1 id="a059" class="kc kd ec bk bj jf ke lp kg lq ki lr kk ls km lt ko">Whats Next?</h1>
<div class="figure gx gy gz ha hb cz dr hc cd hd he hf hg hh ba hi hj hk hl hm hn paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy/q32.png" /></p>
<figcaption><p><em>RAM and ROM usage in Application Build Log.
From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/logs/build-application.log"
class="at cg hq hr hs ht" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/logs/build-application.log</a>
</em></p></figcaption>
</div>
<p id="4c07" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We have created an NB-IoT GPS
Tracker in only <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/l476/logs/build-application.log"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow"><strong class="gj hp">84 KB of
Flash ROM</strong></a> (with debugging symbols included). Mighty impressive considering that it
includes Mynewt Embedded OS and the Embedded Rust Libraries!</p>
<p id="3d72" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">STM32 L476 is definitely a good
choice for building an NB-IoT GPS Tracker. Mynewt did a great job of shielding the
microcontroller-specific details and making embedded applications truly portable. And the application
was created with only a few lines of Rust application code… Rust is incredibly productive for creating
embedded applications!</p>
<p id="4263" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">For my next article I shall be
taking a break from STM32 (since we have proved that its so easy to port Mynewt applications across
STM32 microcontrollers)… And explore <a
href="https://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.0.pdf"
class="at cg hq hr hs ht" target="_blank" rel="noopener nofollow">Nordic nRF52832</a> with Mynewt
and Rust!</p>
</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:00 Dec 04, 2019 AND RETRIEVED FROM THE
INTERNET ARCHIVE ON 23:13:41 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):
LoadShardBlock: 206.117 (3)
PetaboxLoader3.datanode: 145.259 (4)
RedisCDXSource: 0.649
exclusion.robots.policy: 0.461
exclusion.robots: 0.472
CDXLines.iter: 22.513 (3)
captures_list: 232.651
esindex: 0.011
PetaboxLoader3.resolve: 26.915
load_resource: 117.202
-->