2021-12-30 10:58:30 +08:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< meta name = "generator" content = "rustdoc" >
< title > LoRaWAN on Apache NuttX OS< / title >
<!-- Begin scripts/articles/* - header.html: Article Header for Custom Markdown files processed by rustdoc, like chip8.md -->
< meta property = "og:title"
content="LoRaWAN on Apache NuttX OS"
data-rh="true">
< meta property = "og:description"
content="Porting Semtech's LoRaWAN Stack to Apache NuttX OS... And testing it on PineDio Stack BL604 RISC-V Board"
data-rh="true">
< meta property = "og:image"
content="https://lupyuen.github.io/images/lorawan3-title.jpg">
< meta property = "og:type"
content="article" data-rh="true">
<!-- End scripts/articles/* - header.html -->
<!-- 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 = "../dark.css" >
< 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 class = "rustdoc" >
<!-- [if lte IE 8]>
< div class = "warning" >
This old browser is unsupported and will most likely display funky
things.
< / div >
<![endif]-->
<!-- Begin scripts/rustdoc - before.html: Pre - HTML for Custom Markdown files processed by rustdoc, like chip8.md -->
<!-- Begin Theme Picker -->
< div class = "theme-picker" style = "left: 0" > < button id = "theme-picker" aria-label = "Pick another theme!" > < img src = "../brush.svg"
width="18" alt="Pick another theme!">< / button >
< div id = "theme-choices" > < / div >
< / div >
< script src = "../theme.js" > < / script >
< script src = "../prism.js" > < / script >
<!-- Theme Picker -->
<!-- End scripts/rustdoc - before.html -->
< h1 class = "title" > LoRaWAN on Apache NuttX OS< / h1 >
< nav id = "TOC" > < ul >
< li > < a href = "#small-steps" > 1 Small Steps< / a > < ul >
< li > < a href = "#lorawan-support" > 1.1 LoRaWAN Support< / a > < ul > < / ul > < / li >
2021-12-30 18:14:03 +08:00
< li > < a href = "#dependencies" > 1.2 Dependencies< / a > < ul > < / ul > < / li > < / ul > < / li >
2021-12-31 01:42:31 +08:00
< li > < a href = "#lorawan-objective" > 2 LoRaWAN Objective< / a > < ul > < / ul > < / li >
2021-12-31 09:48:18 +08:00
< li > < a href = "#download-source-code" > 3 Download Source Code< / a > < ul > < / ul > < / li >
< li > < a href = "#device-eui-join-eui-and-app-key" > 4 Device EUI, Join EUI and App Key< / a > < ul > < / ul > < / li >
< li > < a href = "#build" > 5 Build< / a > < ul > < / ul > < / li >
< li > < a href = "#join-network" > 6 Join Network< / a > < ul > < / ul > < / li >
< li > < a href = "#nimble-porting-layer" > 7 NimBLE Porting Layer< / a > < ul > < / ul > < / li >
< li > < a href = "#gpio-interrupts" > 8 GPIO Interrupts< / a > < ul > < / ul > < / li >
< li > < a href = "#build-nimble" > 9 Build NimBLE< / a > < ul > < / ul > < / li >
< li > < a href = "#sx1262-busy" > 10 SX1262 Busy< / a > < ul > < / ul > < / li >
< li > < a href = "#event-loop" > 11 Event Loop< / a > < ul > < / ul > < / li >
< li > < a href = "#nonce" > 12 Nonce< / a > < ul > < / ul > < / li >
< li > < a href = "#random-number-generator" > 13 Random Number Generator< / a > < ul > < / ul > < / li >
< li > < a href = "#logging" > 14 Logging< / a > < ul > < / ul > < / li >
< li > < a href = "#message-size" > 15 Message Size< / a > < ul > < / ul > < / li >
< li > < a href = "#send-data" > 16 Send Data< / a > < ul > < / ul > < / li >
< li > < a href = "#spi-with-dma" > 17 SPI with DMA< / a > < ul > < / ul > < / li >
< li > < a href = "#whats-next" > 18 What’ s Next< / a > < ul > < / ul > < / li >
< li > < a href = "#notes" > 19 Notes< / a > < ul > < / ul > < / li >
< li > < a href = "#appendix-gpio-issue" > 20 Appendix: GPIO Issue< / a > < ul > < / ul > < / li >
< li > < a href = "#appendix-callout-issue" > 21 Appendix: Callout Issue< / a > < ul > < / ul > < / li > < / ul > < / nav > < p > 📝 < em > 7 Jan 2022< / em > < / p >
2021-12-30 11:49:59 +08:00
< p > < img src = "https://lupyuen.github.io/images/lorawan3-title.jpg" alt = "PineDio Stack BL604 RISC-V Board (left) talking LoRaWAN to RAKwireless WisGate LoRaWAN Gateway (right)" / > < / p >
< p > < em > PineDio Stack BL604 RISC-V Board (left) talking LoRaWAN to RAKwireless WisGate LoRaWAN Gateway (right)< / em > < / p >
< p > Last article we got < strong > LoRa< / strong > (the long-range, low-bandwidth wireless network) running on < a href = "https://lupyuen.github.io/articles/nuttx" > < strong > Apache NuttX OS< / strong > < / a > …< / p >
2021-12-30 10:58:30 +08:00
< ul >
2021-12-30 11:49:59 +08:00
< li > < a href = "https://lupyuen.github.io/articles/sx1262" > < strong > “LoRa SX1262 on Apache NuttX OS”< / strong > < / a > < / li >
2021-12-30 10:58:30 +08:00
< / ul >
2021-12-30 11:49:59 +08:00
< p > Today we shall run < strong > LoRaWAN< / strong > on NuttX OS!< / p >
2021-12-30 11:51:32 +08:00
< p > < em > Why would we need LoRaWAN?< / em > < / p >
2021-12-30 11:49:59 +08:00
< p > LoRa will work perfectly fine for unsecured < strong > Point-to-Point Wireless Communication< / strong > .< / p >
2021-12-30 10:58:30 +08:00
< p > But if we need to < strong > relay data packets< / strong > securely to a Local Area Network or to the internet, we need < strong > LoRaWAN< / strong > .< / p >
< p > < a href = "https://makezine.com/2021/05/24/go-long-with-lora-radio/" > (More about LoRaWAN)< / a > < / p >
2021-12-30 11:49:59 +08:00
< p > We shall test LoRaWAN on NuttX with Bouffalo Lab’ s < a href = "https://lupyuen.github.io/articles/pinecone" > < strong > BL602 and BL604 RISC-V SoCs< / strong > < / a > .< / p >
< p > (It will probably run on < strong > ESP32< / strong > , since we’ re calling standard NuttX Interfaces)< / p >
< p > < img src = "https://lupyuen.github.io/images/sx1262-library5.jpg" alt = "Porting LoRaWAN to NuttX OS" / > < / p >
2021-12-30 10:58:30 +08:00
< h1 id = "small-steps" class = "section-header" > < a href = "#small-steps" > 1 Small Steps< / a > < / h1 >
2021-12-30 18:14:03 +08:00
< p > In the last article we created a < strong > LoRa Library for NuttX< / strong > (top right) that works with < strong > Semtech SX1262 Transceiver< / strong > …< / p >
2021-12-30 16:35:12 +08:00
< ul >
2021-12-30 18:14:03 +08:00
< li > < a href = "https://github.com/lupyuen/lora-sx1262/tree/lorawan" > < strong > lupyuen/lora-sx1262 (lorawan branch)< / strong > < / a > < / li >
2021-12-30 16:35:12 +08:00
< / ul >
2021-12-30 18:14:03 +08:00
< p > Today we’ ll create a < strong > LoRaWAN Library for NuttX< / strong > (centre right)…< / p >
2021-12-30 10:58:30 +08:00
< ul >
2021-12-30 18:14:03 +08:00
< li > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx" > < strong > lupyuen/LoRaMac-node-nuttx< / strong > < / a > < / li >
< / ul >
< p > That’ s a near-identical fork of < strong > Semtech’ s LoRaWAN Stack< / strong > (dated 14 Dec 2021)…< / p >
< ul >
< li > < a href = "https://github.com/Lora-net/LoRaMac-node" > < strong > Lora-net/LoRaMac-node< / strong > < / a > < / li >
2021-12-30 10:58:30 +08:00
< / ul >
2021-12-30 18:29:00 +08:00
< p > We’ ll test with this < strong > LoRaWAN App< / strong > on NuttX…< / p >
< ul >
< li > < a href = "https://github.com/lupyuen/lorawan_test" > < strong > lupyuen/lorawan_test< / strong > < / a > < / li >
< / ul >
2021-12-30 10:58:30 +08:00
< h2 id = "lorawan-support" class = "section-header" > < a href = "#lorawan-support" > 1.1 LoRaWAN Support< / a > < / h2 >
2021-12-30 18:14:03 +08:00
< p > < em > Why did we fork Semtech’ s LoRaWAN Stack? Why not build it specifically for NuttX?< / em > < / p >
2021-12-30 10:58:30 +08:00
< p > LoRaWAN works < strong > slightly differently across the world regions< / strong > , to comply with Local Wireless Regulations: Radio Frequency, Maximum Airtime (Duty Cycle), < a href = "https://lupyuen.github.io/articles/lorawan#appendix-lora-carrier-sensing" > Listen Before Talk< / a > , …< / p >
< p > Thus we should port < strong > Semtech’ s LoRaWAN Stack< / strong > to NuttX with < strong > minimal changes< / strong > , in case of future updates. (Like for new regions)< / p >
2021-12-30 18:14:03 +08:00
< p > < em > How did we create the LoRaWAN Library?< / em > < / p >
< p > We followed the steps below to create < strong > “nuttx/libs/liblorawan”< / strong > by cloning a NuttX Library…< / p >
2021-12-30 10:58:30 +08:00
< ul >
< li > < a href = "https://lupyuen.github.io/articles/sx1262#appendix-create-a-nuttx-library" > < strong > “Create a NuttX Library”< / strong > < / a > < / li >
< / ul >
2021-12-30 18:14:03 +08:00
< p > Then we replaced the “liblorawan” folder by a < strong > Git Submodule< / strong > that contains our LoRaWAN code… < / p >
2021-12-30 10:58:30 +08:00
< div class = "example-wrap" > < pre class = "language-bash" > < code > cd nuttx/nuttx/libs
2021-12-30 18:14:03 +08:00
rm -r liblorawan
git rm -r liblorawan
git submodule add https://github.com/lupyuen/LoRaMac-node-nuttx liblorawan< / code > < / pre > < / div >
< p > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx" > (To add the LoRaWAN Library to your NuttX Project, see this)< / a > < / p >
< h2 id = "dependencies" class = "section-header" > < a href = "#dependencies" > 1.2 Dependencies< / a > < / h2 >
< p > Our LoRaWAN Library should work on < strong > any NuttX platform< / strong > (like ESP32), assuming that the following dependencies are installed…< / p >
2021-12-30 10:58:30 +08:00
< ul >
< li >
2021-12-30 18:14:03 +08:00
< p > < a href = "https://github.com/lupyuen/lora-sx1262/tree/lorawan" > < strong > lupyuen/lora-sx1262 (lorawan branch)< / strong > < / a > < / p >
< p > LoRa Library for Semtech SX1262 Transceiver< / p >
< p > < a href = "https://lupyuen.github.io/articles/sx1262" > (See this)< / a > < / p >
< / li >
< li >
< p > < a href = "https://github.com/lupyuen/nimble-porting-nuttx" > < strong > lupyuen/nimble-porting-nuttx< / strong > < / a > < / p >
< p > NimBLE Porting Layer multithreading library< / p >
< p > < a href = "https://lupyuen.github.io/articles/sx1262#multithreading-with-nimble-porting-layer" > (See this)< / a > < / p >
2021-12-30 10:58:30 +08:00
< / li >
< li >
2021-12-30 18:14:03 +08:00
< p > < a href = "https://github.com/lupyuen/incubator-nuttx/tree/lorawan/drivers/rf" > < strong > spi_test_driver (/dev/spitest0)< / strong > < / a > < / p >
< p > SPI Test Driver< / p >
< p > < a href = "https://lupyuen.github.io/articles/spi2" > (See this)< / a > < / p >
2021-12-30 10:58:30 +08:00
< / li >
< / ul >
2021-12-30 18:14:03 +08:00
< p > Our LoRa SX1262 Library assumes that the following < strong > NuttX Devices< / strong > are configured…< / p >
2021-12-30 10:58:30 +08:00
< ul >
< li >
2021-12-30 18:14:03 +08:00
< p > < strong > /dev/gpio0< / strong > : GPIO Input for SX1262 Busy Pin< / p >
2021-12-30 10:58:30 +08:00
< / li >
< li >
2021-12-30 18:14:03 +08:00
< p > < strong > /dev/gpio1< / strong > : GPIO Output for SX1262 Chip Select< / p >
< / li >
< li >
< p > < strong > /dev/gpio2< / strong > : GPIO Interrupt for SX1262 DIO1 Pin< / p >
< / li >
< li >
2021-12-30 20:20:16 +08:00
< p > < strong > /dev/spi0< / strong > : SPI Bus for SX1262< / p >
< / li >
< li >
2021-12-30 18:14:03 +08:00
< p > < strong > /dev/spitest0< / strong > : SPI Test Driver (see above)< / p >
2021-12-30 10:58:30 +08:00
< / li >
< / ul >
2021-12-31 01:42:31 +08:00
< h1 id = "lorawan-objective" class = "section-header" > < a href = "#lorawan-objective" > 2 LoRaWAN Objective< / a > < / h1 >
< p > < em > What shall we accomplish with LoRaWAN today?< / em > < / p >
< p > We’ ll do the basic LoRaWAN use case on NuttX…< / p >
< ul >
< li >
2021-12-31 10:02:51 +08:00
< p > Join NuttX to the < strong > LoRaWAN Network< / strong > < / p >
2021-12-31 01:42:31 +08:00
< / li >
< li >
< p > Send a < strong > Data Packet< / strong > from NuttX to LoRaWAN< / p >
< / li >
< / ul >
< p > Which works like this…< / p >
2021-12-31 09:48:18 +08:00
< p > < img src = "https://lupyuen.github.io/images/lorawan3-flow.jpg" alt = "LoRaWAN Use Case" / > < / p >
2021-12-31 01:42:31 +08:00
< ol >
< li >
< p > NuttX sends a < strong > Join Network Request< / strong > to the LoRaWAN Gateway.< / p >
< p > Inside the Join Network Request are…< / p >
2021-12-31 10:02:51 +08:00
< p > < strong > Device EUI:< / strong > Unique ID that’ s assigned to our LoRaWAN Device< / p >
< p > < strong > Join EUI:< / strong > Identifies the LoRaWAN Network that we’ re joining< / p >
2021-12-31 10:24:15 +08:00
< p > < strong > Nonce:< / strong > Non-repeating number, to prevent < a href = "https://en.wikipedia.org/wiki/Replay_attack" > Replay Attacks< / a > < / p >
2021-12-31 14:41:03 +08:00
< p > < em > (EUI means Extended Unique Identifier)< / em > < / p >
2021-12-31 01:42:31 +08:00
< / li >
< li >
< p > LoRaWAN Gateway returns a < strong > Join Network Response< / strong > < / p >
2021-12-31 14:41:03 +08:00
< p > < em > (Which contains the Device Address)< / em > < / p >
2021-12-31 01:42:31 +08:00
< / li >
< li >
< p > NuttX sends a < strong > Data Packet< / strong > to the LoRaWAN Network< / p >
2021-12-31 14:41:03 +08:00
< p > < em > (Which has the Device Address and Payload “Hi NuttX”)< / em > < / p >
2021-12-31 01:42:31 +08:00
< / li >
< li >
< p > NuttX uses an < strong > App Key< / strong > to sign the Join Network Request and the Data Packet< / p >
2021-12-31 14:41:03 +08:00
< p > < em > (App Key is stored inside NuttX, never exposed over the airwaves)< / em > < / p >
2021-12-31 01:42:31 +08:00
< / li >
< / ol >
2021-12-31 14:27:01 +08:00
< p > In a while we’ ll set the Device EUI, Join EUI and App Key in our code.< / p >
2021-12-31 09:48:18 +08:00
< h1 id = "download-source-code" class = "section-header" > < a href = "#download-source-code" > 3 Download Source Code< / a > < / h1 >
2021-12-31 14:27:01 +08:00
< p > To run LoRaWAN on NuttX, download the modified source code for < strong > NuttX OS and NuttX Apps< / strong > …< / p >
< div class = "example-wrap" > < pre class = "language-bash" > < code > mkdir nuttx
cd nuttx
git clone --recursive --branch lorawan https://github.com/lupyuen/incubator-nuttx nuttx
git clone --recursive --branch lorawan https://github.com/lupyuen/incubator-nuttx-apps apps< / code > < / pre > < / div >
< p > Or if we prefer to < strong > add the LoRaWAN Library< / strong > to our NuttX Project, follow these instructions…< / p >
< ol >
< li >
< p > < a href = "https://github.com/lupyuen/incubator-nuttx/tree/lorawan/drivers/rf" > < strong > “Install SPI Test Driver”< / strong > < / a > < / p >
< / li >
< li >
< p > < a href = "https://github.com/lupyuen/nimble-porting-nuttx" > < strong > “Install NimBLE Porting Layer”< / strong > < / a > < / p >
< / li >
< li >
< p > < a href = "https://github.com/lupyuen/lora-sx1262/tree/lorawan" > < strong > “Install LoRa SX1262 Library”< / strong > < / a > < / p >
< / li >
< li >
< p > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx" > < strong > “Install LoRaWAN Library”< / strong > < / a > < / p >
< / li >
< li >
< p > < a href = "https://github.com/lupyuen/lorawan_test" > < strong > “Install LoRaWAN Test App”< / strong > < / a > < / p >
< / li >
< / ol >
< p > Let’ s configure the LoRaWAN code.< / p >
2021-12-31 09:48:18 +08:00
< h1 id = "device-eui-join-eui-and-app-key" class = "section-header" > < a href = "#device-eui-join-eui-and-app-key" > 4 Device EUI, Join EUI and App Key< / a > < / h1 >
2021-12-31 14:27:01 +08:00
< p > < em > Where do we get the Device EUI, Join EUI and App Key?< / em > < / p >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > LoRa Frequency and Sync Word are OK … Let’ s fix the Device EUI and Join EUI for #LoRaWAN on #NuttX OS< / p >
< p > TODO55< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-run2a.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/b91c1f88645eedb813cfffa2bdf7d7a0" > (Run Log)< / a > < / p >
< p > TODO59< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-run1.png" alt = "" / > < / p >
< p > #LoRaWAN gets its Device EUI, Join EUI and App Key from the Secure Element … But since #NuttX doesn’ t have a Secure Element, we hardcode them in the “Soft” Secure Element< / p >
< p > TODO61< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-secure1.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx/blob/master/src/peripherals/soft-se/se-identity.h#L65-L79" > (Source)< / a > < / p >
< p > For #NuttX OS we hardcode the #LoRaWAN App Key … Into the “Soft” Secure Element< / p >
< p > TODO60< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-secure2a.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx/blob/master/src/peripherals/soft-se/se-identity.h#L100-L115" > (Source)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "build" class = "section-header" > < a href = "#build" > 5 Build< / a > < / h1 >
2021-12-30 16:57:37 +08:00
< p > TODO< / p >
< p > #LoRaWAN on #NuttX OS: Let’ s stub out the functions for Non-Volatile Memory and Real Time Clock … And watch what happens 🌋< / p >
< p > TODO39< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-build4a.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx/blob/master/src/nuttx.c" > (Source)< / a > < / p >
< p > #LoRaWAN builds OK on #NuttX OS! 🎉 … Will it run? 🤔< / p >
< ul >
< li >
< p > < a href = "https://github.com/lupyuen/incubator-nuttx/tree/lorawan" > < strong > NuttX OS< / strong > < / a > < / p >
< / li >
< li >
< p > < a href = "https://github.com/lupyuen/incubator-nuttx-apps/tree/lorawan" > < strong > NuttX Apps< / strong > < / a > < / p >
< / li >
< / ul >
2021-12-31 09:48:18 +08:00
< p > < img src = "https://lupyuen.github.io/images/spi2-pinedio1.jpg" alt = "Inside PineDio Stack BL604" / > < / p >
< h1 id = "join-network" class = "section-header" > < a href = "#join-network" > 6 Join Network< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Let’ s connect Apache #NuttX OS to a #LoRaWAN Gateway … RAKwireless WisGate D4H with ChirpStack< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-title.jpg" alt = "PineDio Stack BL604 RISC-V Board (left) talking LoRaWAN to RAKwireless WisGate LoRaWAN Gateway (right)" / > < / p >
< p > < a href = "https://lupyuen.github.io/articles/wisgate" > (Article)< / a > < / p >
< p > #LoRaWAN Gateway receives the Join Request from #NuttX OS … And accepts the Join Request! 🎉< / p >
< p > TODO43< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-chirpstack.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/a8e834e7b4267345f01b6629fb7f5e33" > (Run Log)< / a > < / p >
< p > #NuttX OS doesn’ t handle the Join Response from #LoRaWAN Gateway … Let’ s fix this< / p >
< p > TODO56< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-run3.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/a8e834e7b4267345f01b6629fb7f5e33" > (Run Log)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "nimble-porting-layer" class = "section-header" > < a href = "#nimble-porting-layer" > 7 NimBLE Porting Layer< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Our #NuttX App was waiting for the #LoRaWAN Join Request to be transmitted before receiving the Join Response … But because we’ re polling SX1262, we missed the Join Response … Let’ s fix this with the multithreading functions from NimBLE Porting Layer< / p >
< ul >
< li > < a href = "https://github.com/lupyuen/nimble-porting-nuttx" > < strong > nimble-porting-nuttx< / strong > < / a > < / li >
< / ul >
< p > TODO57< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-run4a.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/d3d9db37a40d7560fc211408db04a81b" > (Log)< / a > < / p >
< p > NimBLE Porting Layer is a portable library of Multithreading Functions … We’ ve used it for #LoRa on Linux and FreeRTOS … Now we call it from Apache #NuttX OS< / p >
2021-12-31 09:48:18 +08:00
< h1 id = "gpio-interrupts" class = "section-header" > < a href = "#gpio-interrupts" > 8 GPIO Interrupts< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > SX1262 will trigger a GPIO Interrupt on #NuttX OS when it receives a #LoRa Packet … We wait for the GPIO Interrupt to be Signalled in a Background Thread< / p >
< p > TODO46< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-gpio2.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/lora-sx1262/blob/lorawan/src/sx126x-nuttx.c#L742-L778" > (Source)< / a > < / p >
< p > We handle GPIO Interrupts (SX1262 DIO1) in a #NuttX Background Thread … Awaiting the Signal for GPIO Interrupt< / p >
< p > TODO47< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-gpio3.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/lora-sx1262/blob/lorawan/src/sx126x-nuttx.c#L835-L861" > (Source)< / a > < / p >
< p > Our #NuttX Background Thread handles the GPIO Interrupts (SX1262 DIO1) … By adding to the #LoRaWAN Event Queue< / p >
< p > TODO48< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-gpio4a.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/lora-sx1262/blob/lorawan/src/sx126x-nuttx.c#L863-L892" > (Source)< / a > < / p >
< p > #LoRaWAN runs neater on Apache #NuttX OS … After implementing Timers and Multithreading with NimBLE Porting Layer … No more sleep()!< / p >
< p > < a href = "https://gist.github.com/lupyuen/cad58115be4cabe8a8a49c0e498f1c95" > (Log)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "build-nimble" class = "section-header" > < a href = "#build-nimble" > 9 Build NimBLE< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > To build NumBLE Porting Layer on #NuttX OS we need to enable: 1️ ⃣ POSIX Timers & Message Queues 2️ ⃣ Clock Monotonic 3️ ⃣ Work Queues 4️ ⃣ SIGEV_THHREAD< / p >
< ul >
< li > < a href = "https://github.com/lupyuen/nimble-porting-nuttx" > < strong > nimble-porting-nuttx< / strong > < / a > < / li >
< / ul >
< p > TODO33< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-config1.png" alt = "" / > < / p >
< p > TODO14< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-config4.png" alt = "" / > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "sx1262-busy" class = "section-header" > < a href = "#sx1262-busy" > 10 SX1262 Busy< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Here’ s how we check the SX1262 Busy Pin on #NuttX OS … By reading the GPIO Input< / p >
< p > TODO49< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-gpio1.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/lora-sx1262/blob/lorawan/src/sx126x-nuttx.c#L184-L199" > (Source)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "event-loop" class = "section-header" > < a href = "#event-loop" > 11 Event Loop< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Here’ s our #LoRaWAN Event Loop for #NuttX OS … Implemented with NimBLE Porting Library … No more polling!< / p >
< p > TODO54< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-npl1.png" alt = "" / > < / p >
< p > TODO58< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-run5a.png" alt = "" / > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "nonce" class = "section-header" > < a href = "#nonce" > 12 Nonce< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Our #NuttX App resends the same Nonce to the #LoRaWAN Gateway … Which (silently) rejects the Join Request due to Duplicate Nonce … Let’ s fix our Random Number Generator< / p >
< p > TODO34< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-chirpstack2a.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/b38434c3d27500444382bb4a066691e5" > (Log)< / a > < / p >
< p > #LoRaWAN gets the Nonce from the Secure Element’ s Random Number Generator … Let’ s simulate the Secure Element on Apache #NuttX OS< / p >
< p > TODO51< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-nonce2a.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx/blob/master/src/mac/LoRaMacCrypto.c#L980-L996" > (Source)< / a > < / p >
< p > Here’ s how we generate #LoRaWAN Nonces on #NuttX OS … With Strong Random Numbers thanks to Entropy Pool< / p >
< p > TODO53< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-nonce6.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx/blob/master/src/nuttx.c#L136-L153" > (Source)< / a > < / p >
< p > Our #NuttX App now sends Random #LoRaWAN Nonces to the LoRaWAN Gateway … And are happily accepted by the gateway! 🎉< / p >
< p > TODO36< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-nonce7a.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/8f012856b9eb6b9a762160afd83df7f8" > (Log)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "random-number-generator" class = "section-header" > < a href = "#random-number-generator" > 13 Random Number Generator< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > For #NuttX Random Number Generator, select the Entropy Pool … To generate Strong Random Numbers for our #LoRaWAN Nonce< / p >
< p > TODO35< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-nonce4a.png" alt = "" / > < / p >
< p > We enable the Entropy Pool in #NuttX OS … To generate Strong Random Numbers for our #LoRaWAN Nonce< / p >
< p > TODO52< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-nonce3a.png" alt = "" / > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "logging" class = "section-header" > < a href = "#logging" > 14 Logging< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Our #NuttX App was too busy to receive the #LoRaWAN Join Response … Let’ s disable the logging< / p >
< p > TODO62< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-tx.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/8f012856b9eb6b9a762160afd83df7f8" > (Log)< / a > < / p >
< p > After disabling logging, our #NuttX App successfully joins the #LoRaWAN Network! 🎉 Now we transmit some Data Packets over LoRaWAN< / p >
< p > TODO63< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-tx3.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/0d301216bbf937147778bb57ab0ccf89" > (Log)< / a > < / p >
< p > Our #LoRaWAN Gateway receives Data Packets from #NuttX OS! 🎉 The Message Payload is empty … Let’ s figure out why 🤔< / p >
< p > TODO44< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-chirpstack5.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/0d301216bbf937147778bb57ab0ccf89" > (Log)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "message-size" class = "section-header" > < a href = "#message-size" > 15 Message Size< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Our #NuttX App sent an empty #LoRaWAN Message because our message is too long for LoRaWAN Data Rate 2 (max 11 bytes) … Let’ s increase the Data Rate to 3< / p >
< p > TODO65< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-tx4a.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/5fc07695a6c4bb48b5e4d10eb05ca9bf" > (Log)< / a > < / p >
< p > Here’ s how we increase the #LoRaWAN Data Rate to 3 in our #NuttX App< / p >
< p > TODO67< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-tx5a.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/lorawan_test/blob/main/lorawan_test_main.c#L57-L70" > (Source)< / a > < / p >
< p > #LoRaWAN Data Rate has been increased to 3 … Max Message Size is now 53 bytes for our #NuttX App< / p >
< p > TODO37< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-tx7a.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/83be5da091273bb39bad6e77cc91b68d" > (Log)< / a > < / p >
< p > #LoRaWAN Gateway now receives the correct Data Packet from our #NuttX App! 🎉< / p >
< p > TODO45< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-chirpstack6.png" alt = "" / > < / p >
< p > < a href = "https://gist.github.com/lupyuen/83be5da091273bb39bad6e77cc91b68d" > (Log)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "send-data" class = "section-header" > < a href = "#send-data" > 16 Send Data< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > Here’ s how we send a #LoRaWAN Data Packet on #NuttX OS … And validate the Packet Size before sending< / p >
< p > TODO68< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-tx6.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/lorawan_test/blob/main/lorawan_test_main.c#L311-L339" > (Source)< / a > < / p >
< p > #LoRaWAN tested OK on Apache #NuttX OS … From #PineDio Stack BL604 @ThePine64 to RAKwireless WisGate … And back! 🎉< / p >
< ul >
< li > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx" > < strong > LoRaMac-node-nuttx< / strong > < / a > < / li >
< / ul >
2021-12-31 09:48:18 +08:00
< h1 id = "spi-with-dma" class = "section-header" > < a href = "#spi-with-dma" > 17 SPI with DMA< / a > < / h1 >
2021-12-30 10:58:30 +08:00
< p > TODO< / p >
2021-12-31 09:48:18 +08:00
< h1 id = "whats-next" class = "section-header" > < a href = "#whats-next" > 18 What’ s Next< / a > < / h1 >
2021-12-31 01:49:00 +08:00
< p > TODO< / p >
< p > CBOR, TTN, Temperature Sensor< / p >
2021-12-30 10:58:30 +08:00
< p > In our next article we’ ll move on to < strong > LoRaWAN!< / strong > < / p >
< p > (Which will be super interesting because of multithreading)< / p >
< p > We’ ll port Semtech’ s < strong > Reference LoRaWAN Stack< / strong > to NuttX…< / p >
< ul >
< li > < a href = "https://github.com/lupyuen/LoRaMac-node-nuttx" > < strong > lupyuen/LoRaMac-node-nuttx< / strong > < / a > < / li >
< / ul >
< p > < em > We’ re porting plenty of code to NuttX: LoRa, LoRaWAN and NimBLE Porting Layer. Do we expect any problems?< / em > < / p >
< p > Yep we might have issues keeping our LoRaWAN Stack in sync with Semtech’ s version. < a href = "https://lupyuen.github.io/articles/sx1262#notes" > (But we shall minimise the changes)< / a > < / p >
< p > Stay Tuned!< / p >
< p > Many Thanks to my < a href = "https://github.com/sponsors/lupyuen" > < strong > GitHub Sponsors< / strong > < / a > for supporting my work! This article wouldn’ t have been possible without your support.< / p >
< 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/articles/book" > Read “The RISC-V BL602 / BL604 Book”< / 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 >
< p > < em > Got a question, comment or suggestion? Create an Issue or submit a Pull Request here…< / em > < / p >
< p > < a href = "https://github.com/lupyuen/lupyuen.github.io/blob/master/src/lorawan3.md" > < code > lupyuen.github.io/src/lorawan3.md< / code > < / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "notes" class = "section-header" > < a href = "#notes" > 19 Notes< / a > < / h1 >
2021-12-30 10:58:30 +08:00
< ol >
< li >
< p > This article is the expanded version of < a href = "https://twitter.com/MisterTechBlog/status/1473593455699841027" > this Twitter Thread< / a > < / p >
< / li >
< li >
< p > We’ re < strong > porting plenty of code< / strong > to NuttX: LoRa, LoRaWAN and NimBLE Porting Layer. Do we expect any problems?< / p >
< ul >
< li >
< p > If we implement LoRa and LoRaWAN as < strong > NuttX Drivers< / strong > , we’ ll have to scrub the code to comply with the < a href = "https://nuttx.apache.org/docs/latest/contributing/coding_style.html" > < strong > NuttX Coding Conventions< / strong > < / a > .< / p >
< p > This makes it < strong > harder to update< / strong > the LoRaWAN Driver when there are changes in the LoRaWAN Spec. (Like for a new LoRaWAN Region)< / p >
< p > < a href = "https://lupyuen.github.io/articles/lorawan#appendix-lora-carrier-sensing" > (Here’ s an example)< / a > < / p >
< / li >
< li >
< p > Alternatively we may implement LoRa and LoRaWAN as < strong > External Libraries< / strong > , similar to < a href = "https://github.com/lupyuen/incubator-nuttx-apps/tree/master/wireless/bluetooth/nimble" > < strong > NimBLE for NuttX< / strong > < / a > .< / p >
< p > (The < a href = "https://github.com/lupyuen/incubator-nuttx-apps/blob/master/wireless/bluetooth/nimble/Makefile#L33" > < strong > Makefile< / strong > < / a > downloads the External Library during build)< / p >
< p > But then we won’ t get a proper NuttX Driver that exposes the ioctl() interface to NuttX Apps.< / p >
< / li >
< / ul >
< p > Conundrum. Lemme know your thoughts!< / p >
< / li >
< li >
< p > How do other Embedded Operating Systems implement LoRaWAN?< / p >
< ul >
< li >
< p > < strong > Mynewt< / strong > embeds a < a href = "https://github.com/apache/mynewt-core/tree/master/net/lora/node" > < strong > Partial Copy< / strong > < / a > of Semtech’ s LoRaWAN Stack into its source tree.< / p >
< / li >
< li >
< p > < strong > Zephyr< / strong > maintains a < a href = "https://github.com/zephyrproject-rtos/loramac-node" > < strong > Complete Fork< / strong > < / a > of the entire LoRaWAN Repo by Semtech. Which gets embedded during the Zephyr build.< / p >
< / li >
< / ul >
< p > The Zephyr approach is probably the best way to < strong > keep our LoRaWAN Stack in sync< / strong > with Semtech’ s.< / p >
< / li >
< li >
< p > We have already ported LoRaWAN to < strong > BL602 IoT SDK< / strong > < a href = "https://lupyuen.github.io/articles/lorawan" > (see this)< / a > , why are we porting again to NuttX?< / p >
< p > Regrettably BL602 IoT SDK has been revamped (without warning) to the < strong > new “hosal” HAL< / strong > < a href = "https://twitter.com/MisterTechBlog/status/1456259223323508748" > (see this)< / a > , and the LoRaWAN Stack will < strong > no longer work< / strong > on the revamped BL602 IoT SDK.< / p >
< p > For easier maintenance, we shall < strong > code our BL602 and BL604 projects with Apache NuttX OS< / strong > instead.< / p >
< p > (Which won’ t get revamped overnight!)< / p >
< / li >
< li >
< p > Will NuttX become the official OS for PineDio Stack BL604 when it goes on sale?< / p >
< p > It might! But first let’ s get LoRaWAN (and ST7789) running on PineDio Stack.< / p >
< / li >
< / ol >
2021-12-31 09:48:18 +08:00
< h1 id = "appendix-gpio-issue" class = "section-header" > < a href = "#appendix-gpio-issue" > 20 Appendix: GPIO Issue< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 14:32:20 +08:00
< p > Switching a #NuttX GPIO Interrupt Pin to Trigger On Rising Edge … Crashes with an Assertion Failure … I’ ll submit a NuttX Issue, meanwhile I have disabled the assertion< / p >
< p > TODO50< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-int.png" alt = "" / > < / p >
2021-12-30 16:35:12 +08:00
< p > < a href = "https://github.com/lupyuen/incubator-nuttx/blob/lorawan/drivers/ioexpander/gpio.c#L544-L547" > (Source)< / a > < / p >
2021-12-31 09:48:18 +08:00
< h1 id = "appendix-callout-issue" class = "section-header" > < a href = "#appendix-callout-issue" > 21 Appendix: Callout Issue< / a > < / h1 >
2021-12-30 16:53:54 +08:00
< p > TODO< / p >
2021-12-30 16:35:12 +08:00
< p > NimBLE Porting Layer doesn’ t work for multiple Callout Timers on #NuttX OS, unless we loop the thread … Will submit a Pull Request to Apache NimBLE 👍< / p >
< p > TODO42< / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-callout.png" alt = "" / > < / p >
< p > < a href = "https://github.com/lupyuen/nimble-porting-nuttx/blob/master/porting/npl/nuttx/src/os_callout.c#L35-L70" > (Source)< / a > < / p >
< p > < img src = "https://lupyuen.github.io/images/lorawan3-title2.jpg" alt = "PineDio Stack BL604 RISC-V Board (left) talking LoRaWAN to RAKwireless WisGate LoRaWAN Gateway (right)" / > < / p >
2021-12-30 10:58:30 +08:00
< / body >
< / html >