mirror of
https://github.com/lupyuen/lupyuen.github.io.git
synced 2025-01-13 10:18:33 +08:00
584 lines
No EOL
37 KiB
HTML
584 lines
No EOL
37 KiB
HTML
<!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 PineDio Stack BL604 RISC-V Board</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 PineDio Stack BL604 RISC-V Board"
|
||
data-rh="true">
|
||
<meta property="og:description"
|
||
content="How we test LoRaWAN on the new PineDio Stack BL604 RISC-V Board"
|
||
data-rh="true">
|
||
<meta property="og:image"
|
||
content="https://lupyuen.github.io/images/lorawan2-title.jpg">
|
||
<meta property="og:type"
|
||
content="article" data-rh="true">
|
||
<link rel="canonical" href="https://lupyuen.org/articles/lorawan2.html" />
|
||
<!-- 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");
|
||
}
|
||
</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>
|
||
<!-- Theme Picker -->
|
||
|
||
<!-- End scripts/rustdoc-before.html -->
|
||
|
||
|
||
<h1 class="title">LoRaWAN on PineDio Stack BL604 RISC-V Board</h1>
|
||
<nav id="rustdoc"><ul>
|
||
<li><a href="#lora-sx1262-transceiver" title="LoRa SX1262 Transceiver">1 LoRa SX1262 Transceiver</a><ul></ul></li>
|
||
<li><a href="#lorawan-firmware" title="LoRaWAN Firmware">2 LoRaWAN Firmware</a><ul>
|
||
<li><a href="#deselect-spi-peripherals" title="Deselect SPI Peripherals">2.1 Deselect SPI Peripherals</a><ul></ul></li>
|
||
<li><a href="#swap-spi-pins" title="Swap SPI Pins">2.2 Swap SPI Pins</a><ul></ul></li></ul></li>
|
||
<li><a href="#run-the-firmware" title="Run The Firmware">3 Run The Firmware</a><ul>
|
||
<li><a href="#lorawan-commands" title="LoRaWAN Commands">3.1 LoRaWAN Commands</a><ul></ul></li></ul></li>
|
||
<li><a href="#lorawan-gateway" title="LoRaWAN Gateway">4 LoRaWAN Gateway</a><ul></ul></li>
|
||
<li><a href="#logic-analyser" title="Logic Analyser">5 Logic Analyser</a><ul></ul></li>
|
||
<li><a href="#spectrum-analyser" title="Spectrum Analyser">6 Spectrum Analyser</a><ul></ul></li>
|
||
<li><a href="#security" title="Security">7 Security</a><ul>
|
||
<li><a href="#cryptographic-co-processor" title="Cryptographic Co-Processor">7.1 Cryptographic Co-Processor</a><ul></ul></li>
|
||
<li><a href="#lorawan-alternatives" title="LoRaWAN Alternatives">7.2 LoRaWAN Alternatives</a><ul></ul></li></ul></li>
|
||
<li><a href="#seeking-volunteers" title="Seeking Volunteers!">8 Seeking Volunteers!</a><ul></ul></li>
|
||
<li><a href="#whats-next" title="What’s Next">9 What’s Next</a><ul></ul></li>
|
||
<li><a href="#notes" title="Notes">10 Notes</a><ul></ul></li></ul></nav><p><img src="https://lupyuen.github.io/images/lorawan2-title.jpg" alt="Tiny tasty treat… PineDio Stack BL604 RISC-V Board" /></p>
|
||
<p><em>Tiny tasty treat… PineDio Stack BL604 RISC-V Board</em></p>
|
||
<p>📝 <em>16 Sep 2021</em></p>
|
||
<p>Previously I wrote about testing the prototype <strong>PineDio Stack BL604</strong> RISC-V Board…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/pinedio"><strong>“PineDio Stack BL604 RISC-V Board: Testing The Prototype”</strong></a></li>
|
||
</ul>
|
||
<p>Today we dive into the most exciting component on PineDio Stack: <strong>Semtech SX1262 Transceiver</strong> for <strong>LoRa and LoRaWAN Networking</strong>.</p>
|
||
<p><em>Why LoRa?</em></p>
|
||
<p><a href="https://makezine.com/2021/05/24/go-long-with-lora-radio/"><strong>LoRa</strong></a> is a <strong>Low-Power, Long-Range, Low-Bandwidth</strong> wireless network.</p>
|
||
<p>LoRa is perfect for <strong>IoT Sensor Devices</strong> that run on Battery Power. (Or Solar Power)</p>
|
||
<p>Since PineDio Stack comes with a <a href="https://lupyuen.github.io/articles/pinedio"><strong>Solar Panel</strong></a>, it will work really well for Agriculture Sensors.</p>
|
||
<p>(And many other IoT gadgets out there in the sun)</p>
|
||
<p><em>Will LoRa support all kinds of messages?</em></p>
|
||
<p>Not quite. LoRa only supports <strong>Short Messages</strong> of up to <a href="https://lora-developers.semtech.com/documentation/tech-papers-and-guides/lora-and-lorawan"><strong>242 Bytes</strong></a>.</p>
|
||
<p>And because LoRa is a Low Power (best effort) network, <strong>messages may get dropped.</strong></p>
|
||
<p>Which is probably OK for sensor devices that send data periodically.</p>
|
||
<p>(But not for texting your friends)</p>
|
||
<p><a href="https://makezine.com/2021/05/24/go-long-with-lora-radio/">(More about LoRa)</a></p>
|
||
<p><em>Is LoRa secure?</em></p>
|
||
<p>LoRa messages are delivered securely when we join a <strong>LoRaWAN Network</strong>.</p>
|
||
<p>Though our <strong>Security Keys</strong> would also need to be <strong>stored securely</strong> on PineDio Stack.</p>
|
||
<p>(We’ll learn how in a while)</p>
|
||
<p><em>Which Pine64 devices will talk LoRa and LoRaWAN?</em></p>
|
||
<p>Once the drivers are implemented, these Pine64 devices will talk LoRa and LoRaWAN to PineDio Stack…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://wiki.pine64.org/wiki/Pinedio"><strong>PineDio LoRa Gateway</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://wiki.pine64.org/wiki/Pinedio#Pinephone_backplate"><strong>PinePhone with LoRa Backplate</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://wiki.pine64.org/wiki/Pinedio#USB_adapter"><strong>Pine64 LoRa USB Adapter</strong></a></p>
|
||
</li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-pine64.jpg" alt="PineDio Gateway, PinePhone Backplate and USB Adapter" /></p>
|
||
<p>This article describes the (pre-production) <strong>PineDio Stack Prototype</strong> thus…</p>
|
||
<blockquote>
|
||
<p>⚠️ <em><strong>Obligatory Disclaimer:</strong> Features included in The Prototype are not complete, and will most certainly undergo changes before becoming available for public consumption. (Burp) They are described here for testing, exploration, education and entertainment purposes only. The Prototype shall NOT be used in production gadgets. (Like toasters, microwave ovens, and most definitely not, pressure cookers)</em></p>
|
||
</blockquote>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-board.jpg" alt="LoRa SX1262 Transceiver on PineDio Stack BL604" /></p>
|
||
<p><a href="https://electronics.stackexchange.com/questions/335912/can-i-break-a-radio-tranceiving-device-by-operating-it-with-no-antenna-connected"><strong>CAUTION</strong>: Always connect the Antenna before Powering On… Or the LoRa Transceiver may get damaged! See this</a></p>
|
||
<h1 id="lora-sx1262-transceiver"><a class="doc-anchor" href="#lora-sx1262-transceiver">§</a>1 LoRa SX1262 Transceiver</h1>
|
||
<p>According to the PineDio Stack Schematic…</p>
|
||
<ul>
|
||
<li><a href="https://wiki.pine64.org/wiki/Pinedio#PineDio_Stack"><strong>PineDio Stack Schematic (Prototype)</strong></a></li>
|
||
</ul>
|
||
<p>Our <strong>LoRa SX1262 Transceiver</strong> is wired onboard like so…</p>
|
||
<p><img src="https://lupyuen.github.io/images/pinedio-lora.png" alt="LoRa SX1262 Transceiver wired to PineDio Stack BL604" /></p>
|
||
<p>Note that the above SPI Pins are shared with the <strong>SPI Flash and ST7789 Display</strong>…</p>
|
||
<div><table><thead><tr><th style="text-align: center">GPIO Number</th><th style="text-align: left">SPI Pin</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center"><strong><code>17</code></strong></td><td style="text-align: left">Common SDO <em>(MOSI)</em></td></tr>
|
||
<tr><td style="text-align: center"><strong><code>0</code></strong></td><td style="text-align: left">Common SDI <em>(MISO)</em></td></tr>
|
||
<tr><td style="text-align: center"><strong><code>11</code></strong></td><td style="text-align: left">Common SCK</td></tr>
|
||
<tr><td style="text-align: center"><strong><code>14</code></strong></td><td style="text-align: left">CS for SPI Flash</td></tr>
|
||
<tr><td style="text-align: center"><strong><code>20</code></strong></td><td style="text-align: left">CS for ST7789</td></tr>
|
||
<tr><td style="text-align: center"><strong><code>15</code></strong></td><td style="text-align: left">CS for SX1262</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<p><a href="https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names">(More about SDO and SDI)</a></p>
|
||
<p>We set the <strong>Chip Select Pin (CS)</strong> to Low to select the <strong>Active SPI Device</strong>: Either LoRa SX1262, SPI Flash or ST7789 Display…</p>
|
||
<p><img src="https://lupyuen.github.io/images/pinedio-spi.jpg" alt="SPI Bus on PineDio Stack" /></p>
|
||
<p>To test the LoRa SX1262 Transceiver, we define the <strong>GPIO Pin Numbers</strong> like so: <a href="https://github.com/lupyuen/lora-sx1262/blob/master/include/sx126x-board.h#L36-L50">lora-sx1262/sx126x-board.h</a></p>
|
||
<div class="example-wrap"><pre class="language-c"><code>// Below are the pin numbers for PineDio Stack BL604 with onboard SX1262.
|
||
#define SX126X_SPI_IDX 0 // SPI Port 0
|
||
#define SX126X_SPI_SDI_PIN 0 // SPI Serial Data In Pin (formerly MISO)
|
||
#define SX126X_SPI_SDO_PIN 17 // SPI Serial Data Out Pin (formerly MOSI)
|
||
#define SX126X_SPI_CLK_PIN 11 // SPI Clock Pin
|
||
#define SX126X_SPI_CS_PIN 15 // SPI Chip Select Pin
|
||
#define SX126X_SPI_CS_OLD 8 // Unused SPI Chip Select Pin
|
||
#define SX126X_NRESET 18 // Reset Pin
|
||
#define SX126X_DIO1 19 // DIO1
|
||
#define SX126X_BUSY_PIN 10 // Busy Pin
|
||
#define SX126X_DEBUG_CS_PIN 5 // Debug Chip Select Pin, mirrors the High / Low State of SX1262 Chip Select Pin. Set to -1 if not needed.
|
||
#define SX126X_TCXO_WAKEUP_TIME 5 // Time required for the TCXO to wakeup (milliseconds)
|
||
#define SX126X_SPI_BAUDRATE (200 * 1000) // SPI Frequency (200 kHz)</code></pre></div>
|
||
<p>(<code>SX126X_DEBUG_CS_PIN</code> should be set to <code>-1</code> if we’re not debugging. More about the Debug CS Pin later)</p>
|
||
<p>We define the <strong>Chip Select Pins</strong> for SPI Flash and ST7789 Display as well: <a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/customer_app/pinedio_lorawan/pinedio_lorawan/demo.c#L101-L105">pinedio_lorawan/demo.c</a></p>
|
||
<div class="example-wrap"><pre class="language-c"><code>/// GPIO for SPI Flash Chip Select Pin. We must set this to High to deselect SPI Flash.
|
||
#define FLASH_CS_PIN 14
|
||
|
||
/// GPIO for ST7789 SPI Chip Select Pin. We must set this to High to deselect ST7789 Display.
|
||
#define DISPLAY_CS_PIN 20</code></pre></div><h1 id="lorawan-firmware"><a class="doc-anchor" href="#lorawan-firmware">§</a>2 LoRaWAN Firmware</h1>
|
||
<p>To test LoRaWAN on PineDio Stack we shall run this <strong>LoRaWAN Firmware</strong>…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/lupyuen/bl_iot_sdk/tree/master/customer_app/pinedio_lorawan"><strong><code>pinedio_lorawan</code> Firmware</strong></a></li>
|
||
</ul>
|
||
<p>Which calls the following <strong>LoRaWAN and SX1262 Drivers</strong>…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/lupyuen/lorawan"><strong><code>lorawan</code> Driver</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/lupyuen/lora-sx1262"><strong><code>lora-sx1262</code> Driver</strong></a></p>
|
||
</li>
|
||
</ul>
|
||
<p>The firmware and drivers were previously ported from Apache Mynewt operating system to BL602 and BL604…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/lorawan"><strong>“PineCone BL602 Talks LoRaWAN”</strong></a></li>
|
||
</ul>
|
||
<p>Here are the changes we made for PineDio Stack.</p>
|
||
<h2 id="deselect-spi-peripherals"><a class="doc-anchor" href="#deselect-spi-peripherals">§</a>2.1 Deselect SPI Peripherals</h2>
|
||
<p>While testing LoRaWAN (and LoRa SX1262), we need to <strong>deselect all other SPI Peripherals</strong> (SPI Flash and ST7789 Display).</p>
|
||
<p>From <a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/customer_app/pinedio_lorawan/pinedio_lorawan/demo.c#L107-L130">pinedio_lorawan/demo.c</a> …</p>
|
||
<div class="example-wrap"><pre class="language-c"><code>/// Set Chip Select pins to High, to deselect SX1262, SPI Flash and ST7789
|
||
int deselect_spi(void) {
|
||
// Configure Chip Select pins as GPIO Output Pins (instead of GPIO Input)
|
||
int rc;
|
||
rc = bl_gpio_enable_output(FLASH_CS_PIN, 0, 0); assert(rc == 0);
|
||
rc = bl_gpio_enable_output(DISPLAY_CS_PIN, 0, 0); assert(rc == 0);
|
||
rc = bl_gpio_enable_output(SX126X_SPI_CS_PIN, 0, 0); assert(rc == 0);
|
||
if (SX126X_DEBUG_CS_PIN >= 0) { // Mirror SX126X_SPI_CS_PIN
|
||
rc = bl_gpio_enable_output(SX126X_DEBUG_CS_PIN, 0, 0); assert(rc == 0);
|
||
}</code></pre></div>
|
||
<p>First we <strong>configure the Chip Select Pins</strong> for GPIO Output.</p>
|
||
<p>Then we set the <strong>Chip Select Pins to High</strong>, to deselect the SPI Peripherals…</p>
|
||
<div class="example-wrap"><pre class="language-c"><code> // Set Chip Select pins to High, to deselect SX1262, SPI Flash and ST7789
|
||
rc = bl_gpio_output_set(FLASH_CS_PIN, 1); assert(rc == 0);
|
||
rc = bl_gpio_output_set(DISPLAY_CS_PIN, 1); assert(rc == 0);
|
||
rc = bl_gpio_output_set(SX126X_SPI_CS_PIN, 1); assert(rc == 0);
|
||
if (SX126X_DEBUG_CS_PIN >= 0) { // Mirror SX126X_SPI_CS_PIN
|
||
rc = bl_gpio_output_set(SX126X_DEBUG_CS_PIN, 1); assert(rc == 0);
|
||
}
|
||
return 0;
|
||
}</code></pre></div>
|
||
<p>(More about <code>SX126X_DEBUG_CS_PIN</code> when we talk about the Logic Analyser)</p>
|
||
<p>This function is called by the <a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/customer_app/pinedio_lorawan/pinedio_lorawan/lorawan.c#L167-L173"><strong><code>init_lorawan</code> Command</strong></a>, which we’ll run in a while…</p>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-deselect.png" alt="Deselect SPI Peripherals" /></p>
|
||
<p><a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/customer_app/pinedio_lorawan/pinedio_lorawan/lorawan.c#L167-L173">(Source)</a></p>
|
||
<h2 id="swap-spi-pins"><a class="doc-anchor" href="#swap-spi-pins">§</a>2.2 Swap SPI Pins</h2>
|
||
<p>Due to a quirk in the SPI implementation on BL602 and BL604, we need to <strong>swap the SPI Pins</strong> for SDI <em>(formerly MISO)</em> and SDO <em>(formerly MOSI)</em>.</p>
|
||
<p>We do this by calling <strong>GLB_Swap_SPI_0_MOSI_With_MISO</strong> in <a href="https://github.com/lupyuen/lora-sx1262/blob/master/src/sx126x-board.c#L168-L202">lora-sx1262/sx126x-board.c</a> …</p>
|
||
<div class="example-wrap"><pre class="language-c"><code>/// Initialise GPIO Pins and SPI Port. Called by SX126xIoIrqInit.
|
||
void SX126xIoInit( void ) {
|
||
// Configure the pins for GPIO Input / Output
|
||
GpioInitOutput( SX126X_SPI_CS_PIN, 1 );
|
||
GpioInitInput( SX126X_BUSY_PIN, 0, 0 );
|
||
GpioInitInput( SX126X_DIO1, 0, 0 );
|
||
if (SX126X_DEBUG_CS_PIN >= 0) { GpioInitOutput( SX126X_DEBUG_CS_PIN, 1 ); }
|
||
|
||
// Note: We must swap SDI (MISO) and SDO (MOSI)
|
||
// to comply with the SPI Pin Definitions in
|
||
// BL602 / BL604 Reference Manual
|
||
int rc = GLB_Swap_SPI_0_MOSI_With_MISO(ENABLE); assert(rc == 0);</code></pre></div>
|
||
<p><a href="https://lupyuen.github.io/articles/pinedio#spi-pins-are-swapped">(More about swapping SPI Pins)</a></p>
|
||
<p>After swapping the SPI Pins we may <strong>initialise the SPI Port</strong>…</p>
|
||
<div class="example-wrap"><pre class="language-c"><code> // Configure the SPI Port
|
||
rc = spi_init(
|
||
&spi_device, // SPI Device
|
||
SX126X_SPI_IDX, // SPI Port
|
||
0, // SPI Mode: 0 for Controller
|
||
// TODO: Due to a quirk in BL602 SPI, we must set
|
||
// SPI Polarity-Phase to 1 (CPOL=0, CPHA=1).
|
||
// But actually Polarity-Phase for SX126X should be 0 (CPOL=0, CPHA=0).
|
||
1, // SPI Polarity-Phase
|
||
SX126X_SPI_BAUDRATE, // SPI Frequency
|
||
2, // Transmit DMA Channel
|
||
3, // Receive DMA Channel
|
||
SX126X_SPI_CLK_PIN, // SPI Clock Pin
|
||
SX126X_SPI_CS_OLD, // Unused SPI Chip Select Pin
|
||
SX126X_SPI_SDO_PIN, // SPI Serial Data Out Pin (formerly MOSI)
|
||
SX126X_SPI_SDI_PIN // SPI Serial Data In Pin (formerly MISO)
|
||
);
|
||
assert(rc == 0);
|
||
}</code></pre></div>
|
||
<p>Note that the <strong>SPI Polarity-Phase should be 1</strong> and not 0.</p>
|
||
<p>This seems to be another quirk of the SPI implementation on BL602 and BL604…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/spi#spi-phase-looks-sus"><strong>“SPI Phase looks sus”</strong></a></li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-swap.png" alt="Swap SPI Pins and tweak the SPI Polarity-Phase" /></p>
|
||
<p><a href="https://github.com/lupyuen/lora-sx1262/blob/master/src/sx126x-board.c#L168-L202">(Source)</a></p>
|
||
<h1 id="run-the-firmware"><a class="doc-anchor" href="#run-the-firmware">§</a>3 Run The Firmware</h1>
|
||
<p>We <strong>build, flash and run the LoRaWAN Firmware</strong> for PineDio Stack with these steps…</p>
|
||
<ol>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/tsen#build-lorawan-firmware"><strong>“Build LoRaWAN Firmware”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/tsen#flash-lorawan-firmware"><strong>“Flash LoRaWAN Firmware”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/tsen#run-lorawan-firmware"><strong>“Run LoRaWAN Firmware”</strong></a></p>
|
||
</li>
|
||
</ol>
|
||
<p>Now we enter the <strong>LoRaWAN commands</strong> to…</p>
|
||
<ol>
|
||
<li>
|
||
<p><strong>Join a LoRaWAN Network</strong></p>
|
||
<p>(Because we’ll transmit data securely over LoRa)</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Send a Data Packet</strong> to the network</p>
|
||
<p>(So that the packet appears in our LoRaWAN Gateway)</p>
|
||
</li>
|
||
</ol>
|
||
<p>We’ll talk to the <strong>ChirpStack LoRaWAN Gateway</strong> that we have installed here…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/wisgate"><strong>“Build a LoRaWAN Network with RAKwireless WisGate Developer Gateway”</strong></a></li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-commands.png" alt="LoRaWAN Commands" /></p>
|
||
<p><a href="https://github.com/lupyuen/bl_iot_sdk/tree/master/customer_app/pinedio_lorawan#lorawan-commands">(Source)</a></p>
|
||
<h2 id="lorawan-commands"><a class="doc-anchor" href="#lorawan-commands">§</a>3.1 LoRaWAN Commands</h2>
|
||
<p>At the BL604 Command Prompt, enter these <strong>LoRaWAN Commands</strong>…</p>
|
||
<ol>
|
||
<li>
|
||
<p>First we start the <strong>Background Task</strong> that will handle LoRa packets…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>create_task</code></pre></div></li>
|
||
<li>
|
||
<p>Next we initialise the <strong>LoRa SX1262 and LoRaWAN Drivers</strong>…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>init_lorawan</code></pre></div></li>
|
||
<li>
|
||
<p>We set the <strong>Device EUI</strong> (Extended Unique Identifier)…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>las_wr_dev_eui 0x4b:0xc1:0x5e:0xe7:0x37:0x7b:0xb1:0x5b</code></pre></div>
|
||
<p>Change the above EUI to the one in our ChirpStack Gateway: <code>Applications → app → Device EUI</code></p>
|
||
</li>
|
||
<li>
|
||
<p>Set the <strong>App EUI</strong>…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>las_wr_app_eui 0x00:0x00:0x00:0x00:0x00:0x00:0x00:0x00</code></pre></div>
|
||
<p>This is not needed for ChirpStack, thus we set to default <code>0000000000000000</code>.</p>
|
||
</li>
|
||
<li>
|
||
<p>Set the <strong>App Key</strong>…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>las_wr_app_key 0xaa:0xff:0xad:0x5c:0x7e:0x87:0xf6:0x4d:0xe3:0xf0:0x87:0x32:0xfc:0x1d:0xd2:0x5d</code></pre></div>
|
||
<p>We get the App Key from ChirpStack at <code>Applications → app → Devices → device_otaa_class_a → Keys (OTAA) → Application Key</code></p>
|
||
</li>
|
||
<li>
|
||
<p>We send a request to <strong>join the LoRaWAN Network</strong>…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>las_join 3</code></pre></div>
|
||
<p>(Retry up to 3 times)</p>
|
||
</li>
|
||
<li>
|
||
<p>After the ChirpStack LoRaWAN Gateway has accepted our Join Request, we open a <strong>LoRaWAN Application Port</strong>…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>las_app_port open 2</code></pre></div>
|
||
<p>(2 is the Application Port Number)</p>
|
||
</li>
|
||
<li>
|
||
<p>Finally we <strong>send a LoRaWAN Data Packet</strong> containing 5 bytes of data (<code>0x00</code>) to LoRaWAN Port 2…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>las_app_tx 2 5 0</code></pre></div>
|
||
<p>(0 means that this is an Unconfirmed Message, we’re not expecting an acknowledgement from the LoRaWAN Gateway)</p>
|
||
</li>
|
||
</ol>
|
||
<p>We should see this in our PineDio Stack serial terminal…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/lupyuen/bl_iot_sdk/tree/master/customer_app/pinedio_lorawan#output-log"><strong>Output Log for LoRaWAN Firmware</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://www.youtube.com/watch?v=BMMIIiZG6G0"><strong>Watch the Demo Video on YouTube</strong></a></p>
|
||
</li>
|
||
</ul>
|
||
<p>Let’s check our ChirpStack LoRaWAN Gateway!</p>
|
||
<p><a href="https://lupyuen.github.io/articles/lorawan#lorawan-driver">(More about the LoRaWAN Commands)</a></p>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-joinsend.png" alt="LoRaWAN Firmware" /></p>
|
||
<h1 id="lorawan-gateway"><a class="doc-anchor" href="#lorawan-gateway">§</a>4 LoRaWAN Gateway</h1>
|
||
<p>To see the <strong>Join Network Request</strong> and the <strong>Data Packet</strong> received by our ChirpStack LoRaWAN Gateway, we do this…</p>
|
||
<ol>
|
||
<li>
|
||
<p>In ChirpStack, click <strong><code>Applications → app → device_otaa_class_a → LoRaWAN Frames</code></strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Restart PineDio Stack.</p>
|
||
<p>Run the LoRaWAN Commands from the previous section.</p>
|
||
</li>
|
||
<li>
|
||
<p>The <strong>Join Network Request</strong> appears in ChirpStack, followed by the <strong>Data Packet</strong>…</p>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-chirpstack.png" alt="Join Network Request and Data Packet in ChirpStack" /></p>
|
||
</li>
|
||
<li>
|
||
<p>Click the <strong><code>Device Data</code></strong> tab in ChirpStack.</p>
|
||
</li>
|
||
<li>
|
||
<p>On PineDio Stack, run this command to send a Data Packet…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>las_app_tx 2 5 0</code></pre></div></li>
|
||
<li>
|
||
<p>Our Data Packet appears in ChirpStack.</p>
|
||
<p><strong><code>DecodedDataHex</code></strong> shows 5 bytes of zero, which is what we sent…</p>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-chirpstack2.png" alt="Data Packet in ChirpStack" /></p>
|
||
</li>
|
||
</ol>
|
||
<p>LoRaWAN tested OK on PineDio Stack!</p>
|
||
<p>Let’s take a peek inside our LoRa SX1262 Transceiver…</p>
|
||
<p><img src="https://lupyuen.github.io/images/pinedio-logic.jpg" alt="PineDio Stack with Logic Analyser" /></p>
|
||
<h1 id="logic-analyser"><a class="doc-anchor" href="#logic-analyser">§</a>5 Logic Analyser</h1>
|
||
<p><em>How did we find out that the SPI Pins need to be swapped?</em></p>
|
||
<p><em>And the tweaking for SPI Polarity-Phase?</em></p>
|
||
<p>A <strong>Logic Analyser</strong> is super helpful for troubleshooting SPI and other interfacing problems on prototype hardware. (Pic above)</p>
|
||
<p>PineDio Stack’s <strong>GPIO Connector</strong> exposes the SPI Pins: SDO <em>(formerly MOSI)</em>, SDI <em>(formerly MISO)</em> and SCK…</p>
|
||
<p><img src="https://lupyuen.github.io/images/pinedio-gpio2.jpg" alt="PineDio Stack GPIO Connector" /></p>
|
||
<p>We <strong>connect our Logic Analyser</strong> to the GPIO Connector like so…</p>
|
||
<div><table><thead><tr><th style="text-align: center">GPIO Number</th><th style="text-align: left">SPI Pin</th><th style="text-align: center">Connector Pin</th></tr></thead><tbody>
|
||
<tr><td style="text-align: center"><strong><code>17</code></strong></td><td style="text-align: left">Common SDO <em>(MOSI)</em></td><td style="text-align: center"><code>7</code></td></tr>
|
||
<tr><td style="text-align: center"><strong><code>0</code></strong></td><td style="text-align: left">Common SDI <em>(MISO)</em></td><td style="text-align: center"><code>17</code></td></tr>
|
||
<tr><td style="text-align: center"><strong><code>11</code></strong></td><td style="text-align: left">Common SCK</td><td style="text-align: center"><code>4</code></td></tr>
|
||
<tr><td style="text-align: center"><strong><code>5</code></strong></td><td style="text-align: left">Debug CS</td><td style="text-align: center"><code>2</code></td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<p><img src="https://lupyuen.github.io/images/pinedio-logic2.jpg" alt="Logic Analyser connected to PineDio Stack" /></p>
|
||
<p><em>What about the SX1262 Chip Select Pin: GPIO 15?</em></p>
|
||
<p>Unfortunately <strong>GPIO 15 is not exposed</strong> on the GPIO Connector.</p>
|
||
<p>Hence we designate GPIO 5 as the <strong>Debug CS Pin</strong> that mirrors the GPIO High / Low state of GPIO 15. <a href="https://github.com/lupyuen/bl_iot_sdk/commit/91f7e751594066d4b97fc5d351c46e74ccded00e#diff-f571fdf8eada0589c0db580e990078fa53eeaf373b8eb7bd738363f16f9954ad">(Here’s how)</a></p>
|
||
<p>Then we simply connect our Logic Analyser to <strong>GPIO 5 as the Chip Select Pin.</strong> (Pic above)</p>
|
||
<p>Our Logic Analyser shows that BL604 is indeed talking correctly to SX1262 over SPI…</p>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-logic.png" alt="LoRa SX1262 with Logic Analyser" /></p>
|
||
<h1 id="spectrum-analyser"><a class="doc-anchor" href="#spectrum-analyser">§</a>6 Spectrum Analyser</h1>
|
||
<p>We’ve used a Logic Analyser to sniff the data inside our LoRa Transceiver. Now we use a <strong>Spectrum Analyser</strong> to sniff the data in the airwaves!</p>
|
||
<p>Our Spectrum Analyser is the <strong>Airspy R2 Software Defined Radio</strong>, which will sniff a range of radio frequences…</p>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-airspy.jpg" alt="Airspy R2 SDR with PineDio Stack" /></p>
|
||
<p>When we analyse the radio spectrum (with <strong>Cubic SDR</strong>), we see this healthy <strong>radio signal</strong> produced by our LoRa Transceiver…</p>
|
||
<p><img src="https://lupyuen.github.io/images/pinedio-chirp2.jpg" alt="LoRa SX1262 visualised with SDR" /></p>
|
||
<p>This is known as a <strong>LoRa Chirp</strong>.</p>
|
||
<p>LoRa Packets have this unique shape so that the packets can be <strong>transmitted over long distances</strong> in spite of radio interference.</p>
|
||
<p><a href="https://lora-developers.semtech.com/documentation/tech-papers-and-guides/lora-and-lorawan">(Up to 5 kilometres in some urban areas!)</a></p>
|
||
<p>More about LoRa and Software Defined Radio here…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/lora#visualise-lora-with-software-defined-radio"><strong>“Visualise LoRa with Software Defined Radio”</strong></a></li>
|
||
</ul>
|
||
<p>(The “fireflies” look odd though. Are we transmitting with too much power?)</p>
|
||
<h1 id="security"><a class="doc-anchor" href="#security">§</a>7 Security</h1>
|
||
<p><em>Since LoRa packets can be sniffed over the airwaves…</em></p>
|
||
<p><em>How do we transmit data securely over LoRa?</em></p>
|
||
<p>That’s why we join a <strong>LoRaWAN Network</strong> when we transmit data.</p>
|
||
<p>LoRaWAN is a layer on top of LoRa that adds <strong>security features</strong> like…</p>
|
||
<ul>
|
||
<li>
|
||
<p><strong>Message Encryption</strong></p>
|
||
<p>(Messages are encrypted with a 128-bit AES Key)</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Message Integrity Check</strong></p>
|
||
<p>(Prevents tampering and replay of messages)</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Message Routing</strong></p>
|
||
<p>(We relay messages through a trusted LoRaWAN Gateway, instead of peer-to-peer direct messaging)</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Message Throttling</strong></p>
|
||
<p>(Prevents flooding of messages)</p>
|
||
</li>
|
||
</ul>
|
||
<p>More about LoRaWAN Security here…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/wisgate#lorawan-security"><strong>“LoRaWAN Security”</strong></a></li>
|
||
</ul>
|
||
<p><em>What’s the catch?</em></p>
|
||
<p>Well the <strong>LoRaWAN Security Keys</strong> would need to be <strong>stored and accessed securely</strong> on PineDio Stack.</p>
|
||
<p>We should never allow the Security Keys to be exposed.</p>
|
||
<p><em>Doesn’t BL604 securely store Security Keys in its <a href="https://lupyuen.github.io/articles/flash#efuse-configuration">Internal EFuse Storage</a>?</em></p>
|
||
<p>Yes. Though there have been past incidents (on other microcontrollers) where Security Keys in EFuse Storage have been compromised. <a href="https://limitedresults.com/2019/11/pwn-the-esp32-forever-flash-encryption-and-sec-boot-keys-extraction/">(See this)</a></p>
|
||
<h2 id="cryptographic-co-processor"><a class="doc-anchor" href="#cryptographic-co-processor">§</a>7.1 Cryptographic Co-Processor</h2>
|
||
<p><em>Is there a better way to store and access Security Keys?</em></p>
|
||
<p>We could use a <strong>Cryptographic Co-Processor</strong> like this…</p>
|
||
<ul>
|
||
<li><a href="https://www.microchip.com/en-us/product/ATECC608A">Microchip ATECC608A</a></li>
|
||
</ul>
|
||
<p>ATECC608A works with <strong>The Things Network</strong>, the public worldwide LoRaWAN Network…</p>
|
||
<ul>
|
||
<li><a href="https://www.thethingsindustries.com/docs/devices/atecc608a/claim/">ATECC608A Secure Element on The Things Network</a></li>
|
||
</ul>
|
||
<p>It also works with <strong>Helium</strong>, another global LoRaWAN Network…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/helium/ecc508">ATECC608A Library for Helium</a></li>
|
||
</ul>
|
||
<p>There are new dev boards with ATECC608 onboard…</p>
|
||
<ul>
|
||
<li><a href="https://www.cnx-software.com/2021/09/14/portenta-h7-lite-low-cost-arduino-pro-board/">Portenta H7 Lite with ATECC608</a></li>
|
||
</ul>
|
||
<p>This article explains how a microcontroller might connect to a secure network (like LoRaWAN) with ATECC608A…</p>
|
||
<ul>
|
||
<li><a href="https://books.google.com.sg/books?id=3F7XDwAAQBAJ&pg=PA302&lpg=PA302&dq=ATECC608A&source=bl&ots=80tY23LkbA&sig=ACfU3U2Ngp_Rao6FG1hpS2ays4O-vNEkCg&hl=en&sa=X&ved=2ahUKEwi_19-4ovnyAhWXILcAHcpQDaY4MhDoAXoECBIQAw#v=onepage&q=ATECC608A&f=false">Internet of Things: A Confluence of Many Disciplines</a></li>
|
||
</ul>
|
||
<p><em>What’s the catch?</em></p>
|
||
<p>We need to be <strong>extra careful</strong> when working with Cryptographic Co-Processors…</p>
|
||
<p>Once the Security Keys have been injected, <strong>they can never be reset</strong>!</p>
|
||
<p>(Same for EFuse Storage)</p>
|
||
<h2 id="lorawan-alternatives"><a class="doc-anchor" href="#lorawan-alternatives">§</a>7.2 LoRaWAN Alternatives</h2>
|
||
<p><em>Can we send LoRa messages securely… Without LoRaWAN?</em></p>
|
||
<p>Traditional Peer-to-Peer Messaging Protocols (like XMPP and Matrix) won’t run on PineDio Stack with LoRa.</p>
|
||
<p>(Because of LoRa’s tiny lossy packets. And JSON over HTTPS is too heavy for BL604)</p>
|
||
<p>These newer <strong>Peer-to-Peer Messaging Protocols</strong> will probably work with PineDio Stack…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://meshtastic.org/"><strong>Meshtastic</strong></a>: Data Mesh Network for LoRa</p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://hackaday.io/project/161491-qmesh-a-lora-based-voice-mesh-network"><strong>QMesh</strong></a>: Voice Mesh Network for LoRa</p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://mycelium-mesh.net/"><strong>Mycelium Mesh</strong></a>: Text Mesh Network for LoRa</p>
|
||
</li>
|
||
</ul>
|
||
<p>There is an <strong>experimental Matrix protocol</strong> for IoT devices…</p>
|
||
<ul>
|
||
<li><a href="https://matrix.org/blog/2021/06/10/low-bandwidth-matrix-an-implementation-guide">Low Bandwidth Matrix (Experimental)</a></li>
|
||
</ul>
|
||
<p>Maybe we’ll see messaging protocols based on Blockchain…</p>
|
||
<ul>
|
||
<li><a href="https://matheo.uliege.be/bitstream/2268.2/11657/12/thesis.pdf">“Designing a Community-Driven Decentralized Storage Network for IoT Data”</a></li>
|
||
</ul>
|
||
<p><em>But how secure are they?</em></p>
|
||
<p>Calm down, amigo… Sorry I haven’t reviewed their security features.</p>
|
||
<p>Someday I might!</p>
|
||
<p><em>PineDio Stack supports triple comms: LoRa, WiFi AND Bluetooth LE…</em></p>
|
||
<p><em>What can we do with them?</em></p>
|
||
<p>Maybe we can turn PineDio Stack into a (very basic) <strong>Solar-Powered Gateway for LoRa + WiFi + Bluetooth LE</strong>?</p>
|
||
<p>That will <strong>relay LoRa and Bluetooth LE messages</strong> to the internet over WiFi?</p>
|
||
<p>Like for <strong>tracking our pets</strong>? (Excluding hamsters and goldfish)</p>
|
||
<p>Or for connecting our <strong>PineTime watches</strong> to the internet?</p>
|
||
<p>Perhaps <strong>super-accurate geolocation</strong> with LoRa + WiFi + Bluetooth LE?</p>
|
||
<p>Got any ideas? Lemme know!</p>
|
||
<h1 id="seeking-volunteers"><a class="doc-anchor" href="#seeking-volunteers">§</a>8 Seeking Volunteers!</h1>
|
||
<p>I’m really excited that PineDio Stack BL604 will be available soon!</p>
|
||
<p>But in the meantime, JF and I have <strong>plenty to test on PineDio Stack</strong>…</p>
|
||
<ol>
|
||
<li>ST7789 Display <em>(SPI)</em></li>
|
||
<li>LoRa SX1262 <em>(SPI)</em></li>
|
||
<li>SPI Flash <em>(SPI)</em></li>
|
||
<li>Accelerometer <em>(I2C)</em></li>
|
||
<li>Heart Rate Sensor <em>(I2C)</em></li>
|
||
<li>Touch Panel <em>(I2C)</em></li>
|
||
<li>Vibrator <em>(GPIO)</em></li>
|
||
<li>Push Button <em>(GPIO)</em></li>
|
||
<li>WiFi</li>
|
||
<li>Bluetooth LE</li>
|
||
<li>JTAG Debugging</li>
|
||
<li>Battery Charging</li>
|
||
<li>Solar Power</li>
|
||
</ol>
|
||
<p><a href="https://twitter.com/MisterTechBlog"><strong>Please let us know</strong></a> if you’re keen to help! 🙏</p>
|
||
<p><img src="https://lupyuen.github.io/images/lorawan2-ttn3.png" alt="Our new LoRaWAN Gateway for The Things Network" /></p>
|
||
<p><a href="https://www.thethingsnetwork.org/community/singapore/">(Source)</a></p>
|
||
<h1 id="whats-next"><a class="doc-anchor" href="#whats-next">§</a>9 What’s Next</h1>
|
||
<p>In the next article, PineDio Stack shall transmit data to the cloud via the public global LoRaWAN Network… <strong>The Things Network</strong>!</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/ttn"><strong>“The Things Network on PineDio Stack BL604 RISC-V Board”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/cbor"><strong>“Encode Sensor Data with CBOR on BL602”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/tsen"><strong>“Internal Temperature Sensor on BL602”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/payload"><strong>“CBOR Payload Formatter for The Things Network”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/prometheus"><strong>“Monitor IoT Devices in The Things Network with Prometheus and Grafana”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/roblox"><strong>“IoT Digital Twin with Roblox and The Things Network”</strong></a></p>
|
||
</li>
|
||
</ul>
|
||
<p>(Sorry for griping… But why doesn’t Singapore have decent coverage for The Things Network? 🙄)</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/sponsor">Sponsor me a coffee</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://www.reddit.com/r/RISCV/comments/pp5btu/lorawan_on_pinedio_stack_bl604_riscv_board/">Discuss this article on Reddit</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/lorawan2.md"><code>lupyuen.github.io/src/lorawan2.md</code></a></p>
|
||
<h1 id="notes"><a class="doc-anchor" href="#notes">§</a>10 Notes</h1>
|
||
<ol>
|
||
<li>
|
||
<p>This article is the expanded version of <a href="https://twitter.com/MisterTechBlog/status/1436128755987058691">this Twitter Thread</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Here’s a great way run a PineDio Stack BL604 <strong>Regression Test</strong> with GPIO, ADC, SPI, SX1262, LoRa, LoRaWAN and The Things Network</p>
|
||
<p><a href="https://lupyuen.github.io/articles/payload#run-payload-formatter"><strong>“Run Payload Formatter”</strong></a></p>
|
||
<p>This is how we tested the upstream updates from <a href="https://github.com/pine64/bl_iot_sdk"><strong>Pine64’s BL602 IoT SDK</strong></a> before merging them. <a href="https://github.com/lupyuen/bl_iot_sdk/pull/28">(See this)</a></p>
|
||
</li>
|
||
<li>
|
||
<p>However <a href="https://github.com/bouffalolab/bl_iot_sdk"><strong>Bouffalo Lab’s BL602 IoT SDK</strong></a> has just been revamped with the new “hosal” HAL.</p>
|
||
<p><a href="https://twitter.com/MisterTechBlog/status/1456259223323508748">(See this Twitter Thread)</a></p>
|
||
<p>We have <strong>no plans yet to merge with the new HAL</strong>, because it will impact all the articles and code that we have written for <a href="https://lupyuen.github.io/articles/book"><strong>“The RISC-V BL602 / BL604 Book”</strong></a>.</p>
|
||
<p>How shall we proceed? Lemme know what you think! 🙏</p>
|
||
</li>
|
||
</ol>
|
||
|
||
|
||
<!-- Begin scripts/rustdoc-after.html: Post-HTML for Custom Markdown files processed by rustdoc, like chip8.md -->
|
||
|
||
<!-- Begin Theme Picker and Prism Theme -->
|
||
<script src="../theme.js"></script>
|
||
<script src="../prism.js"></script>
|
||
<!-- Theme Picker and Prism Theme -->
|
||
|
||
<!-- End scripts/rustdoc-after.html -->
|
||
|
||
|
||
</body>
|
||
</html> |