mirror of
https://github.com/lupyuen/lupyuen.github.io.git
synced 2025-01-13 09:08:30 +08:00
1878 lines
No EOL
90 KiB
HTML
1878 lines
No EOL
90 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>Flashing Firmware to PineCone BL602</title>
|
||
|
||
|
||
<!-- Begin scripts/articles/*-header.html: Article Header for Custom Markdown files processed by rustdoc, like chip8.md -->
|
||
<meta property="og:title"
|
||
content="Flashing Firmware to PineCone BL602"
|
||
data-rh="true">
|
||
<meta property="og:description"
|
||
content="What happens when we flash RISC-V firmware to PineCone BL602 Board... And what's inside the BL602 Boot Image, Partition Table, Device Tree and EFuse Configuration"
|
||
data-rh="true">
|
||
<meta property="og:image"
|
||
content="https://lupyuen.github.io/images/flash-title.jpg">
|
||
<meta property="og:type"
|
||
content="article" data-rh="true">
|
||
<link rel="canonical" href="https://lupyuen.org/articles/flash.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">Flashing Firmware to PineCone BL602</h1>
|
||
<nav id="rustdoc"><ul>
|
||
<li><a href="#flash-bl602-firmware-with-linux-macos-and-windows" title="Flash BL602 Firmware with Linux, macOS and Windows">1 Flash BL602 Firmware with Linux, macOS and Windows</a><ul>
|
||
<li><a href="#install-rustup" title="Install rustup">1.1 Install rustup</a><ul></ul></li>
|
||
<li><a href="#download-and-build-blflash" title="Download and build blflash">1.2 Download and build blflash</a><ul></ul></li>
|
||
<li><a href="#flash-the-firmware" title="Flash the firmware">1.3 Flash the firmware</a><ul></ul></li>
|
||
<li><a href="#watch-the-firmware-run" title="Watch the firmware run">1.4 Watch the firmware run</a><ul></ul></li></ul></li>
|
||
<li><a href="#what-else-gets-flashed-to-bl602" title="What Else Gets Flashed To BL602?">2 What Else Gets Flashed To BL602?</a><ul>
|
||
<li><a href="#xip-flash-memory-vs-boot-rom" title="XIP Flash Memory vs Boot ROM">2.1 XIP Flash Memory vs Boot ROM</a><ul></ul></li></ul></li>
|
||
<li><a href="#partition-table" title="Partition Table">3 Partition Table</a><ul>
|
||
<li><a href="#partition-entry-for-firmware" title="Partition Entry for Firmware">3.1 Partition Entry for Firmware</a><ul></ul></li>
|
||
<li><a href="#partition-entry-for-device-tree" title="Partition Entry for Device Tree">3.2 Partition Entry for Device Tree</a><ul></ul></li>
|
||
<li><a href="#start-code-uses-partition-table" title="Start Code uses Partition Table">3.3 Start Code uses Partition Table</a><ul></ul></li></ul></li>
|
||
<li><a href="#efuse-configuration" title="EFuse Configuration">4 EFuse Configuration</a><ul>
|
||
<li><a href="#boot-header-configuration" title="Boot Header Configuration">4.1 Boot Header Configuration</a><ul></ul></li></ul></li>
|
||
<li><a href="#boot2-bootloader" title="Boot2 Bootloader">5 Boot2 Bootloader</a><ul></ul></li>
|
||
<li><a href="#firmware-image" title="Firmware Image">6 Firmware Image</a><ul></ul></li>
|
||
<li><a href="#device-tree" title="Device Tree">7 Device Tree</a><ul>
|
||
<li><a href="#gpio-led" title="GPIO LED">7.1 GPIO LED</a><ul></ul></li>
|
||
<li><a href="#gpio-button" title="GPIO Button">7.2 GPIO Button</a><ul></ul></li>
|
||
<li><a href="#uart" title="UART">7.3 UART</a><ul></ul></li>
|
||
<li><a href="#pwm" title="PWM">7.4 PWM</a><ul></ul></li>
|
||
<li><a href="#wifi" title="WiFi">7.5 WiFi</a><ul></ul></li>
|
||
<li><a href="#bluetooth" title="Bluetooth">7.6 Bluetooth</a><ul></ul></li></ul></li>
|
||
<li><a href="#flash-firmware-in-2-stages" title="Flash Firmware in 2 Stages">8 Flash Firmware in 2 Stages</a><ul>
|
||
<li><a href="#flashing-stage-1" title="Flashing Stage 1">8.1 Flashing Stage 1</a><ul></ul></li>
|
||
<li><a href="#flashing-stage-2" title="Flashing Stage 2">8.2 Flashing Stage 2</a><ul></ul></li></ul></li>
|
||
<li><a href="#blflash-vs-blopenflasher" title="blflash vs BLOpenFlasher">9 blflash vs BLOpenFlasher</a><ul></ul></li>
|
||
<li><a href="#whats-next" title="What’s Next">10 What’s Next</a><ul></ul></li>
|
||
<li><a href="#notes" title="Notes">11 Notes</a><ul></ul></li>
|
||
<li><a href="#appendix-grant-access-to-usb-uart" title="Appendix: Grant Access To USB UART">12 Appendix: Grant Access To USB UART</a><ul></ul></li>
|
||
<li><a href="#appendix-bl602-flashing-screenshots" title="Appendix: BL602 Flashing Screenshots">13 Appendix: BL602 Flashing Screenshots</a><ul>
|
||
<li><a href="#linux-arm64" title="Linux Arm64">13.1 Linux Arm64</a><ul></ul></li>
|
||
<li><a href="#macos-catalina" title="macOS Catalina">13.2 macOS Catalina</a><ul></ul></li>
|
||
<li><a href="#windows-10" title="Windows 10">13.3 Windows 10</a><ul></ul></li></ul></li>
|
||
<li><a href="#appendix-bl602-partition-table" title="Appendix: BL602 Partition Table">14 Appendix: BL602 Partition Table</a><ul></ul></li>
|
||
<li><a href="#appendix-bl602-device-tree" title="Appendix: BL602 Device Tree">15 Appendix: BL602 Device Tree</a><ul></ul></li>
|
||
<li><a href="#appendix-bl602-efuse-configuration" title="Appendix: BL602 EFuse Configuration">16 Appendix: BL602 EFuse Configuration</a><ul></ul></li>
|
||
<li><a href="#appendix-bldevcube-flashing-log" title="Appendix: BLDevCube Flashing Log">17 Appendix: BLDevCube Flashing Log</a><ul></ul></li></ul></nav><p><img src="https://lupyuen.github.io/images/flash-title.jpg" alt="PineCone BL602 RISC-V Evaluation Board" /></p>
|
||
<p><em>PineCone BL602 RISC-V Evaluation Board</em></p>
|
||
<p>📝 <em>1 Jan 2021</em></p>
|
||
<p>2020 has been an awesome year for PineCone BL602!</p>
|
||
<ol>
|
||
<li>
|
||
<p>We took a quick peek at <a href="https://lupyuen.github.io/articles/pinecone"><strong>PineCone BL602 RISC-V Evaluation Board</strong></a>…</p>
|
||
</li>
|
||
<li>
|
||
<p>Then we <a href="https://lupyuen.github.io/articles/openocd"><strong>connected PineCone to OpenOCD</strong></a> with a JTAG Debugger…</p>
|
||
</li>
|
||
<li>
|
||
<p>And we <a href="https://lupyuen.github.io/articles/debug"><strong>debugged Rust on PineCone</strong></a> with VSCode and GDB…</p>
|
||
</li>
|
||
</ol>
|
||
<p>Today we shall learn to…</p>
|
||
<ol>
|
||
<li>
|
||
<p><strong>Flash BL602 Firmware</strong> to the PineCone Board with open-source tools on any computer: <strong>Linux x64, Linux Arm64, macOS and Windows</strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Appreciate all the things that we can flash to BL602…</p>
|
||
<ul>
|
||
<li><strong>Partition Table</strong></li>
|
||
<li><strong>EFuse Configuration</strong></li>
|
||
<li><strong>Boot2 Bootloader</strong></li>
|
||
<li><strong>Firmware Image</strong></li>
|
||
<li><strong>Device Tree</strong></li>
|
||
</ul>
|
||
</li>
|
||
</ol>
|
||
<p>And we’ll better understand the (undocumented) internals of the <strong>BL602 RISC-V + WiFi + Bluetooth SoC</strong>!</p>
|
||
<h1 id="flash-bl602-firmware-with-linux-macos-and-windows"><a class="doc-anchor" href="#flash-bl602-firmware-with-linux-macos-and-windows">§</a>1 Flash BL602 Firmware with Linux, macOS and Windows</h1>
|
||
<p>Follow these steps to flash a Firmware Binary File (like <code>nuttx.bin</code> or <code>sdk_app_helloworld.bin</code>) to BL602 from Linux x64, Linux Arm64, macOS and Windows.</p>
|
||
<p>(On Windows: Use plain old Windows CMD Command Prompt to run the commands, not WSL)</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/lupyuen/nuttx/releases/download/upstream-2022-01-26/nuttx.zip">Download demo firmware <code>nuttx.bin</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/lupyuen/bl_iot_sdk/releases/download/v1.0.0/sdk_app_helloworld.bin">Download demo firmware <code>sdk_app_helloworld.bin</code></a></p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="install-rustup"><a class="doc-anchor" href="#install-rustup">§</a>1.1 Install rustup</h2>
|
||
<ol>
|
||
<li>
|
||
<p>Install <code>rustup</code> from <a href="https://rustup.rs"><code>rustup.rs</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p>Select the default options.</p>
|
||
<p><strong>For Windows:</strong> Install <code>rustup</code> under plain old Windows CMD, not WSL</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>For Linux and macOS:</strong> Add Rust to the PATH…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>source $HOME/.cargo/env</code></pre></div></li>
|
||
</ol>
|
||
<h2 id="download-and-build-blflash"><a class="doc-anchor" href="#download-and-build-blflash">§</a>1.2 Download and build blflash</h2>
|
||
<p>We’ll use <a href="https://github.com/spacemeowx2/blflash"><strong><code>blflash</code></strong></a>, the flashing tool created in Rust by <a href="https://github.com/spacemeowx2"><code>spacemeowx2</code></a>.</p>
|
||
<p>(For WSL: Do this under plain old Windows CMD, not WSL, because <code>blflash</code> needs to access the COM port)</p>
|
||
<ol>
|
||
<li>
|
||
<p>Install the <code>blflash</code> tool…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>cargo install blflash</code></pre></div></li>
|
||
<li>
|
||
<p>We should see…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Compiling blflash v0.3.3
|
||
Finished release [optimized] target(s) in 4m 37s
|
||
Installing ~/.cargo/bin/blflash
|
||
Installed package `blflash v0.3.3` (executable `blflash`)</code></pre></div></li>
|
||
<li>
|
||
<p><strong>For Linux:</strong> Grant access to the USB UART port. <a href="https://lupyuen.github.io/articles/flash#appendix-grant-access-to-usb-uart">(Here’s how)</a></p>
|
||
</li>
|
||
</ol>
|
||
<p><img src="https://lupyuen.github.io/images/flash-linux.png" alt="Flashing PineCone BL602 with Manjaro Linux Arm64 on Pinebook Pro" /></p>
|
||
<p><em>Flashing PineCone BL602 with Manjaro Linux Arm64 on Pinebook Pro</em></p>
|
||
<h2 id="flash-the-firmware"><a class="doc-anchor" href="#flash-the-firmware">§</a>1.3 Flash the firmware</h2>
|
||
<p>(For WSL: Do this under plain old Windows CMD, not WSL, because <code>blflash</code> needs to access the COM port)</p>
|
||
<ol>
|
||
<li>
|
||
<p>To flash the firmware, we set BL602 to <strong>Flashing Mode</strong> and restart the board…</p>
|
||
<p><strong>For PineDio Stack BL604:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p>Set the <strong>GPIO 8 Jumper</strong> to <strong>High</strong> <a href="https://lupyuen.github.io/images/pinedio-high.jpg">(Like this)</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Disconnect the USB cable and reconnect</p>
|
||
<p>Or use the Improvised Reset Button <a href="https://lupyuen.github.io/articles/pinedio#appendix-improvised-reset-button-for-pinedio-stack">(Here’s how)</a></p>
|
||
</li>
|
||
</ol>
|
||
<p><strong>For PineCone BL602:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p>Connect PineCone to the USB port</p>
|
||
</li>
|
||
<li>
|
||
<p>Set the <strong>PineCone Jumper (IO 8)</strong> to the <strong><code>H</code> Position</strong> <a href="https://lupyuen.github.io/images/pinecone-jumperh.jpg">(Like this)</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Press the Reset Button</p>
|
||
</li>
|
||
</ol>
|
||
<p><strong>For BL10:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p>Connect BL10 to the USB port</p>
|
||
</li>
|
||
<li>
|
||
<p>Press and hold the <strong>D8 Button (GPIO 8)</strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Press and release the <strong>EN Button (Reset)</strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Release the D8 Button</p>
|
||
</li>
|
||
</ol>
|
||
<p><strong>For <a href="https://docs.ai-thinker.com/en/wb2">Ai-Thinker Ai-WB2</a>, Pinenut and MagicHome BL602:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p>Disconnect the board from the USB Port</p>
|
||
</li>
|
||
<li>
|
||
<p>Connect <strong>GPIO 8</strong> to <strong>3.3V</strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Reconnect the board to the USB port</p>
|
||
</li>
|
||
</ol>
|
||
</li>
|
||
<li>
|
||
<p>Enter this to flash our firmware…</p>
|
||
<p><strong>For Linux:</strong></p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>blflash flash sdk_app_helloworld.bin \
|
||
--port /dev/ttyUSB0 </code></pre></div>
|
||
<p>(Change <code>sdk_app_helloworld.bin</code> to the full path of the firmware binary to be flashed. Change the USB serial port <code>/dev/ttyUSB0</code> if necessary.)</p>
|
||
<p><strong>For macOS:</strong></p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>blflash flash sdk_app_helloworld.bin \
|
||
--port /dev/tty.usbserial-1410 \
|
||
--initial-baud-rate 230400 \
|
||
--baud-rate 230400</code></pre></div>
|
||
<p>(Change <code>sdk_app_helloworld.bin</code> to the full path of the firmware binary to be flashed. Change <code>/dev/tty.usbserial-1420</code> to the USB Serial Device assigned to BL602)</p>
|
||
<p>Note that we’re throttling the USB Serial Port from the default 1 Mbps to 230.4 kbps. blflash won’t work on macOS at 1 Mbps (because it’s not a standard POSIX baud rate).</p>
|
||
<p><strong>For Windows:</strong></p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>blflash flash sdk_app_helloworld.bin --port COM5</code></pre></div>
|
||
<p>(Change <code>sdk_app_helloworld.bin</code> to the full path of the firmware binary to be flashed. Change <code>COM5</code> to the serial port assigned to BL602)</p>
|
||
</li>
|
||
<li>
|
||
<p>We should see…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Start connection...
|
||
5ms send count 55
|
||
handshake sent elapsed 1.059862ms
|
||
Connection Succeed</code></pre></div>
|
||
<p><code>blflash</code> has connected successfully to BL602 over the USB Serial port.</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Bootrom version: 1
|
||
Boot info: BootInfo { len: 14, bootrom_version: 1, otp_info: [0, 0, 0, 0, 3, 0, 0, 0, 61, 9d, c0, 5, b9, 18, 1d, 0] }
|
||
Sending eflash_loader...
|
||
Finished 3.375522563s 8.47KB/s
|
||
5ms send count 500
|
||
handshake sent elapsed 6.51343ms
|
||
Entered eflash_loader</code></pre></div>
|
||
<p><code>blflash</code> starts by sending the <strong>EFlash Loader</strong> program to BL602. Then EFlash Loader starts running on BL602.</p>
|
||
<p>EFlash Loader receives our <strong>Flash Image</strong> from <code>blflash</code> and flashes our firmware to ROM…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Erase flash addr: 0 size: 47504
|
||
Program flash... c85e11a0083a27f72f6e1bab9b67cac98d5d31ed90b64b78e6e89e070d782c58
|
||
Program done 836.9393ms 55.49KB/s
|
||
Skip segment addr: e000 size: 272 sha256 matches
|
||
Skip segment addr: f000 size: 272 sha256 matches
|
||
Erase flash addr: 10000 size: 25216
|
||
Program flash... 86e0abb8907b99dfc8e7771f58aa9c5473fc2439b3aa38613d0ad895681d656e
|
||
Program done 489.5002ms 50.36KB/s
|
||
Skip segment addr: 1f8000 size: 5671 sha256 matches
|
||
Success</code></pre></div>
|
||
<p><code>blflash</code> (and EFlash Loader) has successfully erased and flashed 5 sections in BL602 ROM.</p>
|
||
<p>The ROM sections were extracted from our Flash Image at offsets <code>0x0</code>, <code>0xe000</code>, <code>0xf000</code>, <code>0x10000</code> (that’s our firmware) and <code>0x1f8000</code></p>
|
||
<p>We’ll learn more about this.</p>
|
||
</li>
|
||
<li>
|
||
<p>If we see this…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Start connection...
|
||
5ms send count 115
|
||
handshake sent elapsed 72.001µs
|
||
Retry 1</code></pre></div>
|
||
<p>Or this…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Start connection...
|
||
5ms send count 55
|
||
handshake sent elapsed 850.287µs
|
||
Connection Succeed
|
||
Error: IO error: Operation timed out
|
||
caused by: Operation timed out</code></pre></div>
|
||
<p>Disconnect PineCone from the USB port. Check that the PineCone Jumper (IO 8) is set to <code>H</code>. Retry the flash command.</p>
|
||
</li>
|
||
<li>
|
||
<p>If we see this error…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Sending eflash_loader...
|
||
Finished 2.988880532s 9.56KB/s
|
||
Error: IO error while using serial port: Invalid argument
|
||
caused by: Invalid argument</code></pre></div>
|
||
<p>It probably means that the baud rate is too high. Try a lower baud rate like 115.2 kbps…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>blflash flash sdk_app_helloworld.bin \
|
||
--port /dev/tty.usbserial-1410 \
|
||
--initial-baud-rate 115200 \
|
||
--baud-rate 115200</code></pre></div></li>
|
||
<li>
|
||
<p>If we see this error…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Error: IO error while using serial port:
|
||
Permission denied</code></pre></div>
|
||
<p>Check whether access has been granted for the USB UART port. <a href="https://lupyuen.github.io/articles/flash#appendix-grant-access-to-usb-uart">(Here’s how)</a></p>
|
||
</li>
|
||
</ol>
|
||
<p><a href="https://github.com/apache/nuttx/issues/4336">(Flashing WiFi Firmware for NuttX? See this)</a></p>
|
||
<p><a href="https://lupyuen.github.io/articles/flash#appendix-bl602-flashing-screenshots">(See the flashing screenshots)</a></p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-screen.png" alt="Firmware running on PineCone" /></p>
|
||
<p><em>Firmware running on PineCone</em></p>
|
||
<h2 id="watch-the-firmware-run"><a class="doc-anchor" href="#watch-the-firmware-run">§</a>1.4 Watch the firmware run</h2>
|
||
<ol>
|
||
<li>
|
||
<p>To run our firmware, we set BL602 to <strong>Normal Mode</strong> (Non-Flashing) and restart the board…</p>
|
||
<p><strong>For PineDio Stack BL604:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p>Set the <strong>GPIO 8 Jumper</strong> to <strong>Low</strong> <a href="https://lupyuen.github.io/images/pinedio-low.jpg">(Like this)</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Disconnect the USB cable and reconnect</p>
|
||
<p>Or use the Improvised Reset Button <a href="https://lupyuen.github.io/articles/pinedio#appendix-improvised-reset-button-for-pinedio-stack">(Here’s how)</a></p>
|
||
</li>
|
||
</ol>
|
||
<p><strong>For PineCone BL602:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p>Set the <strong>PineCone Jumper (IO 8)</strong> to the <strong><code>L</code> Position</strong> <a href="https://lupyuen.github.io/images/pinecone-jumperl.jpg">(Like this)</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Press the Reset Button</p>
|
||
</li>
|
||
</ol>
|
||
<p><strong>For BL10:</strong></p>
|
||
<ol>
|
||
<li>Press and release the <strong>EN Button (Reset)</strong></li>
|
||
</ol>
|
||
<p><strong>For <a href="https://docs.ai-thinker.com/en/wb2">Ai-Thinker Ai-WB2</a>, Pinenut and MagicHome BL602:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p>Disconnect the board from the USB Port</p>
|
||
</li>
|
||
<li>
|
||
<p>Connect <strong>GPIO 8</strong> to <strong>GND</strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Reconnect the board to the USB port</p>
|
||
</li>
|
||
</ol>
|
||
</li>
|
||
<li>
|
||
<p>To watch our firmware run, connect to the PineCone Serial Console (at 2 Mbps)…</p>
|
||
<p><strong>For Linux:</strong></p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>screen /dev/ttyUSB0 2000000</code></pre></div>
|
||
<p>(Change the USB serial port <code>/dev/ttyUSB0</code> if necessary)</p>
|
||
<p><strong>For macOS:</strong></p>
|
||
<ol>
|
||
<li>
|
||
<p><a href="https://freeware.the-meiers.org/"><strong>Download CoolTerm</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p>Click <strong><code>Options</code></strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Set <strong><code>Port</code></strong> to <strong><code>usbserial-1420</code></strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Set <strong><code>Baudrate</code></strong> to <strong><code>2000000</code></strong> (2 Mbps)</p>
|
||
</li>
|
||
<li>
|
||
<p>Click <strong><code>Connect</code></strong></p>
|
||
</li>
|
||
</ol>
|
||
<p><img src="https://lupyuen.github.io/images/led-coolterm.png" alt="CoolTerm Options" /></p>
|
||
<p>(Some macOS apps like <code>screen</code> won’t work at 2 Mbps because it’s not a standard POSIX baud rate. See <a href="https://lupyuen.github.io/articles/led#appendix-fix-bl602-demo-firmware-for-macos">“Fix BL602 Demo Firmware for macOS”</a>)</p>
|
||
<p><strong>For Windows:</strong> Use <code>putty</code> to connect to PineCone’s <code>COM</code> Port (like <code>COM5</code>) at speed <code>2000000</code> (2 Mbps)</p>
|
||
<p><a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html">Download putty for Windows</a></p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-putty.png" alt="Connect putty to COM Port at speed 2000000" /></p>
|
||
<p><strong>Web Serial Terminal:</strong> Newer versions of the Chrome Web Browser support the Web Serial API, which also works with BL602…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://googlechromelabs.github.io/serial-terminal/">Web Serial Terminal</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://twitter.com/MisterTechBlog/status/1390908514088878080">How it looks</a></p>
|
||
</li>
|
||
</ul>
|
||
<p>Under <code>Baud Rate</code>, select <code>Custom</code> and enter <code>2000000</code> (2 Mbps)</p>
|
||
</li>
|
||
<li>
|
||
<p>Press the <strong><code>RST</code> Button</strong> on PineCone to restart the board. As PineCone boots, we shall see the console output from our firmware…</p>
|
||
<p>For <a href="https://github.com/lupyuen/nuttx/releases/download/upstream-2022-01-26/nuttx.zip"><code>nuttx.bin</code></a>:</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>NuttShell (NSH) NuttX-10.2.0
|
||
nsh> </code></pre></div>
|
||
<p>For <a href="https://github.com/lupyuen/bl_iot_sdk/releases/download/v1.0.0/sdk_app_helloworld.bin"><code>sdk_app_helloworld.bin</code></a>:</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[helloworld] start
|
||
[helloworld] helloworld
|
||
[helloworld] end</code></pre></div>
|
||
<p><strong>For Linux:</strong> To exit the <code>screen</code> console, press <code>Ctrl-A</code> then <code>k</code> then <code>y</code></p>
|
||
<p><strong>For macOS:</strong> Close the CoolTerm window</p>
|
||
<p><strong>For Windows:</strong> Close the <code>putty</code> window</p>
|
||
</li>
|
||
<li>
|
||
<p>Here’s the console output for BL602 Firmware that supports WiFi and interactive commands: <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/bl602.bin"><code>bl602.bin</code></a></p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-wifi.png" alt="Console output for BL602 WiFi Firmware" /></p>
|
||
<p><em>Console output for BL602 WiFi Firmware</em></p>
|
||
</li>
|
||
<li>
|
||
<p>What happens when we leave the PineCone Jumper (IO 8) in the <code>H</code> Position.. And connect with <code>screen</code> or <code>putty</code>?</p>
|
||
<p>We’ll see that PineCone is stuck in a Holding Pattern, waiting to be flashed…</p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-wait.png" alt="PineCone waiting to be flashed" /></p>
|
||
<p><em>PineCone waiting to be flashed</em></p>
|
||
</li>
|
||
</ol>
|
||
<p>These steps were tested on Arm64 Linux (Pinebook Pro with Manjaro), macOS Catalina and Windows 10.</p>
|
||
<p><strong>For MagicHome BL602 WiFi LED Controller:</strong> This gadget doesn’t have a Reset Button, so it will be hard to see the <code>helloworld</code> message. Use the NuttX firmware <strong><code>nuttx.bin</code></strong> instead…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/lupyuen/nuttx/releases/download/upstream-2022-01-26/nuttx.zip"><strong>Download demo firmware <code>nuttx.bin</code></strong></a></li>
|
||
</ul>
|
||
<p>Or <strong><code>sdk_app_gpio.bin</code> GPIO Demo Firmware</strong>…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/led#control-rgb-led-with-gpio"><strong>“Control RGB LED with GPIO”</strong></a></li>
|
||
</ul>
|
||
<p>Connect at 2 Mbps. When we enter <strong><code>help</code></strong>, it will respond with a list of commands. This is useful for validating that our firmware is running on MagicHome BL602.</p>
|
||
<p>If BL602 isn’t responding, check that the <strong>USB Serial Adapter supports 2 Mbps</strong>. Some adapters don’t support 2 Mbps <a href="https://www.reddit.com/r/RISCV/comments/lnumsv/the_riscv_bl602_book/h455koc/?context=3">(like CP2102)</a>, changing it to FT232R might help.</p>
|
||
<p>Can we configure BL602 to run at a lower Baud Rate? It’s not easy because the Baud Rate is defined inside the <a href="https://lupyuen.github.io/articles/flash#appendix-bl602-device-tree">Device Tree</a>, which needs to be recompiled with the firmware.</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://www.reddit.com/r/RISCV/comments/knsju9/flashing_firmware_to_pinecone_bl602/gn7rw3i?utm_source=share&utm_medium=web2x&context=3"><strong>Discuss MagicHome BL602 on Reddit</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/esphome/feature-requests/issues/1049"><strong>ESPHome Feature Request for MagicHome BL602</strong></a></p>
|
||
</li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps.jpg" alt="BL602 Flashing Process reverse engineered from BLOpenFlasher" /></p>
|
||
<p><em>BL602 Flashing Process reverse engineered from BLOpenFlasher</em></p>
|
||
<h1 id="what-else-gets-flashed-to-bl602"><a class="doc-anchor" href="#what-else-gets-flashed-to-bl602">§</a>2 What Else Gets Flashed To BL602?</h1>
|
||
<p>Whenever we flash the firmware of BL602, <code>blflash</code> transmits to BL602 a <strong>Flash Image</strong> that contains 5 sections of data…</p>
|
||
<div><table><thead><tr><th style="text-align: left">Offset</th><th style="text-align: left">Contents</th></tr></thead><tbody>
|
||
<tr><td style="text-align: left"><strong>Boot2 Bootloader</strong> <br> <code>0x0000 0000</code></td><td style="text-align: left">Code and data for <br>Boot2 Bootloader</td></tr>
|
||
<tr><td style="text-align: left"><strong>Partition Table</strong> <br> <code>0x0000 E000</code></td><td style="text-align: left">Partition Table for <br>Flash Image</td></tr>
|
||
<tr><td style="text-align: left"><strong>Partition Table</strong> <br> <code>0x0000 F000</code></td><td style="text-align: left">Partition Table for <br> Flash Image <br>(For second core?)</td></tr>
|
||
<tr><td style="text-align: left"><strong>Firmware Image</strong> <br> <code>0x0001 0000</code></td><td style="text-align: left">Code and data for <br> Application Firmware</td></tr>
|
||
<tr><td style="text-align: left"><strong>Device Tree</strong> <br> <code>0x001F 8000</code></td><td style="text-align: left">Default settings for<br> peripherals and ports: <br>UART, GPIO, SPI, WiFi, …</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<p>The addresses above are Offsets into the Flash Image that is transmitted by <code>blflash</code> to BL602 for flashing.</p>
|
||
<p>This info was deciphered from the official open-source Go flashing tool for BL602: <strong>BLOpenFlasher</strong>…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher">Source Code for BLOpenFlasher</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Refer to <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/flash_tool.go"><code>flash_tool.go</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p>See <a href="https://github.com/bouffalolab/bl_docs/tree/main/BL602_ISP/en">BL602 ISP Flash Programming Doc</a> for the UART Flashing Protocol</p>
|
||
</li>
|
||
<li>
|
||
<p>See <a href="https://maero.dk/bl602-firmware-image-format/">“Documenting the BouffaloLab BL602 firmware image format”</a></p>
|
||
</li>
|
||
</ul>
|
||
<p>Let’s look at each section of the Flash Image.</p>
|
||
<h2 id="xip-flash-memory-vs-boot-rom"><a class="doc-anchor" href="#xip-flash-memory-vs-boot-rom">§</a>2.1 XIP Flash Memory vs Boot ROM</h2>
|
||
<p>In this article we’ll use “ROM” to refer to BL602’s <strong>XIP Flash Memory</strong> (at address <code>0x2300 0000</code> with size 16 MB).</p>
|
||
<p>(XIP means Execute In Place… BL602 lets us run firmware code from External Flash Memory without transferring to RAM first. <a href="https://lupyuen.github.io/articles/boot#bl602-boot2-bootloader">See this</a>)</p>
|
||
<p>The <a href="https://github.com/bouffalolab/bl_docs/blob/main/BL602_RM/en/BL602_BL604_RM_1.2_en.pdf">BL602 Reference Manual</a> uses “ROM” to refer to BL602’s <strong>Boot ROM</strong> (at address <code>0x2100 0000</code> with size 128 KB).</p>
|
||
<p>BL602’s Boot ROM is explained here…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/boot#bl602-rom-driver-api"><strong>“BL602 ROM Driver API”</strong></a></li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps2c.png" alt="Compiling the BL602 Partition Table" /></p>
|
||
<p><em>Compiling the BL602 Partition Table</em></p>
|
||
<h1 id="partition-table"><a class="doc-anchor" href="#partition-table">§</a>3 Partition Table</h1>
|
||
<p>The <strong>Partition Table</strong> specifies the structure of the Flash Image that will be flashed to ROM. It’s like the ROM Table above… But converted to binary format and transmitted to BL602 (twice).</p>
|
||
<p>Here’s a snippet from BL602’s Partition Table: <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/partition/partition_cfg_2M.toml"><code>partition_cfg_2M.toml</code></a></p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[pt_table]
|
||
# Partition table is 4K in size (0x1000 bytes)
|
||
address0 = 0xE000
|
||
address1 = 0xF000</code></pre></div>
|
||
<p>This says that the Partition Table (4,096 bytes in binary form) is stored at two offsets: <code>0xE000</code> and <code>0xF000</code></p>
|
||
<p>The second Partition Table might possibly be used in future to support a second CPU. <a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/customer_app/bl602_boot2/bl602_boot2/blsp_boot2.c#L475-L505">See this</a></p>
|
||
<h2 id="partition-entry-for-firmware"><a class="doc-anchor" href="#partition-entry-for-firmware">§</a>3.1 Partition Entry for Firmware</h2>
|
||
<p>Here’s the first Partition Entry in the Partition Table…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[[pt_entry]]
|
||
type = 0
|
||
name = "FW"
|
||
device = 0
|
||
address0 = 0x10000
|
||
size0 = 0xC8000
|
||
address1 = 0xD8000
|
||
size1 = 0x88000
|
||
len = 0</code></pre></div>
|
||
<p>It says that our Firmware Image is located at offset <code>0x10000</code>.</p>
|
||
<p><em>(But why two contiguous sections: <code>0x10000</code> and <code>0xD8000</code>?)</em></p>
|
||
<h2 id="partition-entry-for-device-tree"><a class="doc-anchor" href="#partition-entry-for-device-tree">§</a>3.2 Partition Entry for Device Tree</h2><div class="example-wrap"><pre class="language-text"><code>[[pt_entry]]
|
||
type = 7
|
||
name = "factory"
|
||
device = 0
|
||
address0 = 0x1F8000
|
||
size0 = 0x7000
|
||
address1 = 0
|
||
size1 = 0
|
||
len = 0</code></pre></div>
|
||
<p>This is the Partition Entry for the Device Tree at offset <code>0x1F8000</code>. We’ll cover the Device Tree in a while.</p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-start.png" alt="BL602 Start Code refers to the Partition Table" /></p>
|
||
<p><em>BL602 Start Code refers to the Partition Table</em></p>
|
||
<h2 id="start-code-uses-partition-table"><a class="doc-anchor" href="#start-code-uses-partition-table">§</a>3.3 Start Code uses Partition Table</h2>
|
||
<p>The Partition Table is referenced by the Start Code for BL602 Firmware…</p>
|
||
<ul>
|
||
<li>
|
||
<p>Browse the <a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/components/bl602/bl602/evb/src/boot/gcc/start.S">BL602 Start Code</a></p>
|
||
</li>
|
||
<li>
|
||
<p>See <a href="https://lupyuen.github.io/articles/mynewt">“Porting Mynewt to PineCone BL602”</a>, Section 10: <a href="https://lupyuen.github.io/articles/mynewt#implement-start-code">“Implement Start Code”</a></p>
|
||
</li>
|
||
</ul>
|
||
<p><a href="https://lupyuen.github.io/articles/flash#appendix-bl602-partition-table">More about BL602 Partition Table</a></p>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps3.png" alt="Transforming firmware images with BL602 EFuse Configuration" /></p>
|
||
<p><em>Transforming firmware images with BL602 EFuse Configuration</em></p>
|
||
<h1 id="efuse-configuration"><a class="doc-anchor" href="#efuse-configuration">§</a>4 EFuse Configuration</h1>
|
||
<p><em>What’s an EFuse in BL602?</em></p>
|
||
<p>An <strong>EFuse</strong> stores one bit of data (<code>0</code> or <code>1</code>) in a special way… Once an EFuse is set to <code>1</code>, it can never be reset to <code>0</code>.</p>
|
||
<p>BL602 has 1,024 EFuses (1,024 bits).</p>
|
||
<p><em>How are EFuses used in BL602?</em></p>
|
||
<p>Since the EFuses are one-time write-only bits, they are useful for storing Encryption Keys securely.</p>
|
||
<p>Once the Encryption Keys have been injected into BL602’s EFuses, they can never be changed.</p>
|
||
<p><em>Why would we need Encryption Keys in BL602?</em></p>
|
||
<p>To make it harder for unauthorised folks to dump out the BL602 Firmware or tamper with it.</p>
|
||
<p>BL602 disallows the reading of Encryption Keys once they have been set.</p>
|
||
<p><em>Do we really need to encrypt our firmware?</em></p>
|
||
<p>For development we will leave the EFuse Configuration empty, so that our firmware won’t be encrypted.</p>
|
||
<p>EFuse Configuration is used when we’re ready to release a commercial product with BL602 inside.</p>
|
||
<p><a href="https://lupyuen.github.io/articles/boot#efuse-security">How EFuses are used for encrypting and verifying BL602 firmware updates</a></p>
|
||
<p><a href="https://limitedresults.com/2019/11/pwn-the-esp32-forever-flash-encryption-and-sec-boot-keys-extraction/">How EFuses are used in ESP32… And how Encryption Keys were compromised</a></p>
|
||
<p>Snippet from BL602’s EFuse Configuration: <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/efuse_bootheader/efuse_bootheader_cfg.conf"><code>efuse_bootheader_cfg.conf</code></a></p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[EFUSE_CFG]
|
||
ef_sf_aes_mode = 0
|
||
ef_sboot_sign_mode = 0
|
||
ef_sboot_en = 0
|
||
ef_dbg_jtag_dis = 0
|
||
ef_dbg_mode = 0
|
||
ef_dbg_pwd_low = 0
|
||
ef_dbg_pwd_high = 0</code></pre></div><h2 id="boot-header-configuration"><a class="doc-anchor" href="#boot-header-configuration">§</a>4.1 Boot Header Configuration</h2>
|
||
<p>The EFuse Configuration also includes a <strong>Boot Header Configuration</strong> that specifies how the Boot2 Bootloader and Firmware Image should be flashed to ROM.</p>
|
||
<p>Here’s a snippet from <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/efuse_bootheader/efuse_bootheader_cfg.conf"><code>efuse_bootheader_cfg.conf</code></a>…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[BOOTHEADER_CFG]
|
||
magic_code = 0x504e4642
|
||
revision = 0x01
|
||
flashcfg_magic_code = 0x47464346
|
||
io_mode = 4
|
||
cont_read_support = 1
|
||
sfctrl_clk_delay = 1
|
||
sfctrl_clk_invert = 0x01
|
||
|
||
reset_en_cmd = 0x66
|
||
reset_cmd = 0x99
|
||
exit_contread_cmd = 0xff
|
||
exit_contread_cmd_size = 3
|
||
|
||
jedecid_cmd = 0x9f
|
||
jedecid_cmd_dmy_clk = 0
|
||
qpi_jedecid_cmd = 0x9f
|
||
qpi_jedecid_dmy_clk = 0
|
||
|
||
sector_size = 4
|
||
mfg_id = 0xef
|
||
page_size = 256
|
||
|
||
chip_erase_cmd = 0xc7
|
||
sector_erase_cmd = 0x20
|
||
blk32k_erase_cmd = 0x52
|
||
blk64k_erase_cmd = 0xd8
|
||
...</code></pre></div>
|
||
<p>JEDEC refers to the <a href="https://en.wikipedia.org/wiki/Common_Flash_Memory_Interface">Common Flash Memory Interface</a> that’s used to access Flash Memory.</p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-bootheader.png" alt="Boot Header at base of XIP Flash Memory 0x2300 0000" /></p>
|
||
<p>Here we see that the Boot Header (in binary form) is located at the base of XIP Flash Memory (<code>0x2300 0000</code>).</p>
|
||
<p><a href="https://lupyuen.github.io/articles/flash#appendix-bl602-efuse-configuration">More about BL602 EFuse Configuration</a></p>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps2a.png" alt="Transforming BL602 Boot2 Bootloader" /></p>
|
||
<p><em>Transforming the BL602 Boot2 Bootloader</em></p>
|
||
<h1 id="boot2-bootloader"><a class="doc-anchor" href="#boot2-bootloader">§</a>5 Boot2 Bootloader</h1>
|
||
<p>Located at offset <code>0x0</code>, the <strong>Boot2 Bootloader</strong> contains the firmware code that is run first upon booting BL602….</p>
|
||
<ol>
|
||
<li>
|
||
<p><strong>Boot2 Bootloader Binary</strong> is at…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/builtin_imgs/blsp_boot2.bin"><code>blsp_boot2.bin</code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<p>Which gets transformed with the <strong>EFuse Configuration</strong> (and Boot Header Configuration) to create (with firmware offset <code>0x2000</code>)…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/image/boot2image.bin"><code>boot2image.bin</code></a></li>
|
||
</ul>
|
||
<p>(For development, we have disabled encryption in the EFuse Configuration)</p>
|
||
</li>
|
||
<li>
|
||
<p>Which is flashed to BL602 Flash ROM whenever we update the firmware</p>
|
||
</li>
|
||
</ol>
|
||
<p>The BL602 Boot2 Bootloader Source Code is located here…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/lupyuen/bl_iot_sdk/tree/master/customer_app/bl602_boot2">bl_iot_sdk/customer_app/bl602_boot2</a></li>
|
||
</ul>
|
||
<p>The BL602 Boot2 Bootloader is explained in the article…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/boot"><strong>“BL602 Bootloader”</strong></a></li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps2b.png" alt="Transforming BL602 Firmware Image" /></p>
|
||
<p><em>Transforming the BL602 Firmware Image</em></p>
|
||
<h1 id="firmware-image"><a class="doc-anchor" href="#firmware-image">§</a>6 Firmware Image</h1>
|
||
<p>Located at offset <code>0x10000</code>, the <strong>Firmware Image</strong> contains our application firmware code that is run after the boot2 bootloader.</p>
|
||
<p>Our firmware binary (<code>sdk_app_helloworld.bin</code>) gets transformed with the <strong>EFuse Configuration</strong> (and Boot Header Configuration) to create (with firmware offset <code>0x1000</code>)…</p>
|
||
<ul>
|
||
<li><code>bl602/image/fwimage.bin</code></li>
|
||
</ul>
|
||
<p>(For development, we have disabled encryption in the EFuse Configuration)</p>
|
||
<p>The transformed binary is then flashed to BL602 Flash ROM.</p>
|
||
<p><em>Both the Boot2 Bootloader and Firmware Image are compiled to execute at XIP Flash Address <code>0x2300 0000</code>… How can two programs coexist at the same address?</em></p>
|
||
<p><em>Does Boot2 Bootloader contain the code to move Firmware Image to address <code>0x2300 0000</code>, overwriting the Boot2 Bootloader?</em></p>
|
||
<p>Yes indeed! This is explained in the article…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/boot"><strong>“BL602 Bootloader”</strong></a></li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps2d.png" alt="Compiling the BL602 Device Tree" /></p>
|
||
<p><em>Compiling the BL602 Device Tree</em></p>
|
||
<h1 id="device-tree"><a class="doc-anchor" href="#device-tree">§</a>7 Device Tree</h1>
|
||
<p><em>What’s a Device Tree?</em></p>
|
||
<p>In Linux, a <strong>Device Tree</strong> describes the computer hardware and its settings: Board, Memory, SoC, USB Devices, … (In Windows, the hardware settings are stored in the Windows Registry)</p>
|
||
<p>BL602 doesn’t run Linux (yet). But it uses a similar Device Tree to load the <strong>settings for the BL602 peripherals and ports</strong>: GPIO, UART, PWM, SPI, WiFi, …</p>
|
||
<p>Whenever we update the firmware on BL602, the Device Tree is converted to binary format and flashed to BL602 ROM.</p>
|
||
<p><em>Arm Microcontrollers don’t use Device Trees… Is this overkill for BL602?</em></p>
|
||
<p>We may configure BL602’s peripherals and ports through the firmware code by calling the BL602 Hardware Abstraction Layer (HAL). So it’s not mandatory to use the Device Tree.</p>
|
||
<p>Configuring the WiFi stack for BL602 can get cumbersome if we code it in the firmware. Thus it makes sense to embed the WiFi configuration inside the Device Tree. (We’ll see this in a while)</p>
|
||
<p><strong>UPDATE:</strong> Device Trees are used on BL602 because the BL602 IoT SDK is partly based on <a href="https://github.com/alibaba/AliOS-Things"><strong>AliOS Things</strong></a> embedded operating system. This enables AliOS to access BL602 peripherals and ports via the Linux-style <code>/dev</code> name. For example, <code>/dev/ttyS0</code> refers to the UART console.</p>
|
||
<p><em>Which functions in the BL602 HAL will use the Device Tree to configure the BL602 peripherals and ports?</em></p>
|
||
<p>Look for BL602 HAL Functions named <code>dts</code> like…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/components/hal_drv/bl602_hal/hal_gpio.c#L174-L200"><code>hal_gpio_init_from_dts</code></a></li>
|
||
</ul>
|
||
<p>This function initialises the GPIO port by loading the Device Tree from ROM.</p>
|
||
<p>Here are some interesting snippets from the BL602 Device Tree: <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts"><code>bl_factory_params_IoTKitA_40M.dts</code></a></p>
|
||
<p>(“<code>40M</code>” refers to the BL602 Clock Speed: 40 MHz)</p>
|
||
<p>(FYI: Some RISC-V microcontrollers don’t use Device Trees, like GD32 VF103. Device Trees seem to be common among microcontrollers based on SiFive RISC-V Cores, including BL602.)</p>
|
||
<h2 id="gpio-led"><a class="doc-anchor" href="#gpio-led">§</a>7.1 GPIO LED</h2>
|
||
<p>This setting configures GPIO 5 for LED output…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>gpio0 {
|
||
status = "okay";
|
||
pin = <5>;
|
||
feature = "led";
|
||
active = "Hi"; // Hi or Lo
|
||
mode = "blink"; // blink or hearbeat
|
||
time = <100>; // Duration for this mode</code></pre></div>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts#L16-L23">Device Tree Source</a></p>
|
||
<h2 id="gpio-button"><a class="doc-anchor" href="#gpio-button">§</a>7.2 GPIO Button</h2>
|
||
<p>Here we configure GPIO 2 as a Button Input (note the debounce logic)…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>gpio2 {
|
||
status = "okay";
|
||
pin = <2>;
|
||
feature = "button";
|
||
active = "Hi";
|
||
mode = "multipress";
|
||
button {
|
||
debounce = <10>;
|
||
short_press_ms {
|
||
start = <100>;
|
||
end = <3000>;
|
||
kevent = <2>;
|
||
};
|
||
long_press_ms {
|
||
start = <6000>;
|
||
end = <10000>;
|
||
kevent = <3>;
|
||
};
|
||
longlong_press_ms {
|
||
start = <15000>;
|
||
kevent = <4>;
|
||
};
|
||
trig_level = "Hi";</code></pre></div>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts#L32-L57">Device Tree Source</a></p>
|
||
<h2 id="uart"><a class="doc-anchor" href="#uart">§</a>7.3 UART</h2>
|
||
<p>This is the default UART setting for <code>/dev/ttyS0</code>, on GPIO 7 and 16 at 2 Mbps…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>uart@4000A000 {
|
||
status = "okay";
|
||
id = <0>;
|
||
compatible = "bl602_uart";
|
||
path = "/dev/ttyS0";
|
||
baudrate = <2000000>;
|
||
pin {
|
||
rx = <7>;
|
||
tx = <16>;
|
||
};
|
||
buf_size {
|
||
rx_size = <512>;
|
||
tx_size = <512>;
|
||
};
|
||
feature {
|
||
tx = "okay";
|
||
rx = "okay";
|
||
cts = "disable";
|
||
rts = "disable";
|
||
};
|
||
};</code></pre></div>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts#L194-L214">Device Tree Source</a></p>
|
||
<p>There is a second UART Port at <code>/dev/ttyS1</code>, on GPIO 3 and 4 at 115.2 kbps…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>uart@4000A100 {
|
||
status = "okay";
|
||
id = <1>;
|
||
compatible = "bl602_uart";
|
||
path = "/dev/ttyS1";
|
||
baudrate = <115200>;
|
||
pin {
|
||
rx = <3>;
|
||
tx = <4>;
|
||
};
|
||
buf_size {
|
||
rx_size = <512>;
|
||
tx_size = <512>;
|
||
};
|
||
feature {
|
||
tx = "okay";
|
||
rx = "okay";
|
||
cts = "disable";
|
||
rts = "disable";
|
||
};
|
||
};</code></pre></div>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts#L215-L235">Device Tree Source</a></p>
|
||
<h2 id="pwm"><a class="doc-anchor" href="#pwm">§</a>7.4 PWM</h2>
|
||
<p>This PWM setting could be useful for turning PineCone’s onboard RGB LED into a Disco Light…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>pwm {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
pwm@4000A420 {
|
||
status = "okay";
|
||
compatible = "bl602_pwm";
|
||
reg = <0x4000A420 0x20>;
|
||
path = "/dev/pwm0";
|
||
id = <0>;
|
||
pin = <0>;
|
||
freq = <800000>;
|
||
duty = <50>;
|
||
};</code></pre></div>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts#L126-L135">Device Tree Source</a></p>
|
||
<h2 id="wifi"><a class="doc-anchor" href="#wifi">§</a>7.5 WiFi</h2>
|
||
<p>This complicated setting configures the WiFi stack (including SSID)…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>wifi {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
region {
|
||
country_code = <86>;
|
||
};
|
||
mac {
|
||
mode = "MBF";
|
||
sta_mac_addr = [C8 43 57 82 73 40];
|
||
ap_mac_addr = [C8 43 57 82 73 02];
|
||
};
|
||
sta {
|
||
ssid = "yourssid";
|
||
pwd = "yourapssword";
|
||
auto_connect_enable = <0>;
|
||
};
|
||
ap {
|
||
ssid = "bl_test_005";
|
||
pwd = "12345678";
|
||
ap_channel = <11>;
|
||
auto_chan_detect = "disable";
|
||
};</code></pre></div>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts#L281-L333">Device Tree Source</a></p>
|
||
<h2 id="bluetooth"><a class="doc-anchor" href="#bluetooth">§</a>7.6 Bluetooth</h2>
|
||
<p>Bluetooth is configured in the Device Tree too…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>bluetooth {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
brd_rf {
|
||
pwr_table_ble = <13>; //range:-3~15dbm; if set -3, please set 253 here
|
||
};</code></pre></div>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts#L334-L340">Device Tree Source</a></p>
|
||
<p><a href="https://lupyuen.github.io/articles/flash#appendix-bl602-device-tree">More about BL602 Device Tree</a></p>
|
||
<p><a href="https://www.kernel.org/doc/html/latest/devicetree/usage-model.html">More about Linux Device Trees</a></p>
|
||
<p><em>(TODO: Where is the Device Tree stored in XIP Flash ROM? Is this Device Tree used by EFlash Loader or Boot2 Bootloader?)</em></p>
|
||
<h1 id="flash-firmware-in-2-stages"><a class="doc-anchor" href="#flash-firmware-in-2-stages">§</a>8 Flash Firmware in 2 Stages</h1>
|
||
<p>Earlier we saw that our firmware is flashed to BL602 in two stages… (Just like the Falcon Rocket)</p>
|
||
<ol>
|
||
<li>
|
||
<p><strong>Stage 1</strong>: Transmit the <strong>EFlash Loader</strong> to BL602</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Stage 2</strong>: Transmit our Flash Image to the EFlash Loader and write to ROM</p>
|
||
</li>
|
||
</ol>
|
||
<p>Let’s zoom into each stage of the flashing process.</p>
|
||
<p>The BL602 UART Flashing Protocol is explained here…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/bouffalolab/bl_docs/tree/main/BL602_ISP/en">BL602 ISP Flash Programming</a></li>
|
||
</ul>
|
||
<h2 id="flashing-stage-1"><a class="doc-anchor" href="#flashing-stage-1">§</a>8.1 Flashing Stage 1</h2>
|
||
<p>First we transmit the firmware code for the EFlash Loader to BL602 at <strong>512 kbps</strong>… (Slower = More Reliable)</p>
|
||
<ul>
|
||
<li>EFlash Loader Binary: <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/eflash_loader/eflash_loader_40m.bin"><code>eflash_loader_40m.bin</code></a></li>
|
||
</ul>
|
||
<p>(“<code>40m</code>” refers to the BL602 Clock Speed: 40 MHz)</p>
|
||
<p>Then we start running the EFlash Loader on BL602 in RAM at address <a href="https://github.com/lupyuen/bl_iot_sdk/blob/master/tools/flash_tool/bl602/eflash_loader/eflash_loader.map#L7439"><code>0x2201 0000</code></a></p>
|
||
<h2 id="flashing-stage-2"><a class="doc-anchor" href="#flashing-stage-2">§</a>8.2 Flashing Stage 2</h2>
|
||
<p>Next we compose the <strong>Flash Image</strong> that contains 5 sections of data…</p>
|
||
<div><table><thead><tr><th style="text-align: left">Offset</th><th style="text-align: left">Contents</th></tr></thead><tbody>
|
||
<tr><td style="text-align: left"><code>0x0000 0000</code></td><td style="text-align: left"><strong>Boot2 Bootloader</strong> <br>(transformed)</td></tr>
|
||
<tr><td style="text-align: left"><code>0x0000 E000</code></td><td style="text-align: left"><strong>Partition Table</strong> <br>(binary format)</td></tr>
|
||
<tr><td style="text-align: left"><code>0x0000 F000</code></td><td style="text-align: left"><strong>Partition Table</strong> <br>(binary format)</td></tr>
|
||
<tr><td style="text-align: left"><code>0x0001 0000</code></td><td style="text-align: left"><strong>Firmware Image</strong> <br>(transformed)</td></tr>
|
||
<tr><td style="text-align: left"><code>0x001F 8000</code></td><td style="text-align: left"><strong>Device Tree</strong> <br>(binary format)</td></tr>
|
||
</tbody></table>
|
||
</div>
|
||
<p>Then we transmit the Flash Image to EFlash Loader, which updates the BL602 Flash ROM.</p>
|
||
<p>The data is transmitted at <strong>2 Mbps</strong>. (Instead of 512 kbps earlier)</p>
|
||
<p>EFlash Loader must acknowledge the data transfer within 5 seconds. Or the flashing shall be considered failed.</p>
|
||
<p>EFlash Loader is explained here…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/loader"><strong>“BL602 EFlash Loader: Reverse Engineered with Ghidra”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/bouffalolab/bl_docs/tree/main/BL602_ISP/en"><strong>More about EFlash Loader in BL602 ISP Doc</strong></a></p>
|
||
</li>
|
||
</ul>
|
||
<h1 id="blflash-vs-blopenflasher"><a class="doc-anchor" href="#blflash-vs-blopenflasher">§</a>9 blflash vs BLOpenFlasher</h1>
|
||
<p><em>We started this article with blflash (in Rust) … And pivoted to BLOpenFlasher (in Go). Why the switcheroo?</em></p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/bouffalolab/BLOpenFlasher"><strong>BLOpenFlasher</strong></a> is the official open-source flashing tool for BL602… But we couldn’t run make it work on Linux and Windows CMD <a href="https://github.com/bouffalolab/BLOpenFlasher/issues/2">(See this)</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/spacemeowx2/blflash"><strong><code>blflash</code></strong></a> (created by <a href="https://github.com/spacemeowx2"><code>spacemeowx2</code></a>) was derived from BLOpenFlasher and it works great on Linux, macOS and Windows CMD</p>
|
||
</li>
|
||
</ul>
|
||
<p>Hence we’ll use <code>blflash</code> for flashing BL602… But to understand the flashing internals we shall refer to the official reference implementation: BLOpenFlasher.</p>
|
||
<p><strong>UPDATE:</strong> <code>blflash</code> might need to be updated due to changes in the BL602 Embedded Flash. <a href="https://github.com/spacemeowx2/blflash/issues/9">(See this)</a></p>
|
||
<p><em>How different is <code>blflash</code> from BLOpenFlasher?</em></p>
|
||
<ol>
|
||
<li>
|
||
<p><code>blflash</code> transmits the EFlash Loader at <strong>115.2 kbps</strong> (vs <strong>512 kbps</strong> in BLOpenFlasher)</p>
|
||
<p><code>blflash</code> transmits the ROM data to be flashed at <strong>1 Mbps</strong> (vs <strong>2 Mbps</strong> in BLOpenFlasher)</p>
|
||
<p>The transmission speeds may be specified through the command-line options <code>--initial-baud-rate</code> (for EFlash Loader) and <code>--baud-rate</code> (for ROM data)…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>blflash flash sdk_app_helloworld.bin \
|
||
--port /dev/tty.usbserial-1410 \
|
||
--initial-baud-rate 230400 \
|
||
--baud-rate 230400</code></pre></div>
|
||
<p>Note: blflash won’t work on macOS at 1 Mbps because it’s not a standard POSIX baud rate. That’s why we use a lower baud rate like 230.4 kbps.</p>
|
||
</li>
|
||
<li>
|
||
<p><code>blflash</code> doesn’t support compiling Device Trees into binary format.</p>
|
||
<p>It uses a hard-coded binary Device Tree located here…</p>
|
||
<ul>
|
||
<li><strong>Device Tree Binary</strong>: <a href="https://github.com/spacemeowx2/blflash/blob/main/blflash/src/chip/bl602/cfg/ro_params.dtb"><code>ro_params.dtb</code></a></li>
|
||
</ul>
|
||
<p>BLOpenFlasher uses a Python script to compile the Device Tree into binary…</p>
|
||
<ul>
|
||
<li><strong>Compile Device Tree to binary format</strong>: <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/dts2dtb.py"><code>dts2dtb.py</code></a></li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps2d.png" alt="Compiling the BL602 Device Tree" /></p>
|
||
<p><em>Compiling the BL602 Device Tree</em></p>
|
||
</li>
|
||
<li>
|
||
<p>What if we need to modify the Device Tree (like the WiFi SSID settings)?</p>
|
||
<p>We could compile the Device Tree with BLOpenFlasher. Then transfer the compiled Device Tree binary…</p>
|
||
<ul>
|
||
<li><a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/image/ro_params.dtb"><code>bl602/image/ro_params.dtb</code></a></li>
|
||
</ul>
|
||
<p>…from BLOpenFlasher to <code>blflash</code> for flashing.</p>
|
||
</li>
|
||
<li>
|
||
<p>Configuration files and firmware binaries for <code>blflash</code>…</p>
|
||
<ul>
|
||
<li>
|
||
<p><strong>Partition Table</strong>: <a href="https://github.com/spacemeowx2/blflash/blob/main/blflash/src/chip/bl602/cfg/partition_cfg_2M.toml"><code>partition_cfg_2M.toml</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p><strong>EFuse Configuration</strong>: <a href="https://github.com/spacemeowx2/blflash/blob/main/blflash/src/chip/bl602/cfg/efuse_bootheader_cfg.conf"><code>efuse_bootheader_cfg.conf</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Boot2 Bootloader</strong>: <a href="https://github.com/spacemeowx2/blflash/blob/main/blflash/src/chip/bl602/image/blsp_boot2.bin"><code>blsp_boot2.bin</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p><strong>EFlash Loader</strong>: <a href="https://github.com/spacemeowx2/blflash/blob/main/blflash/src/chip/bl602/image/eflash_loader_40m.bin"><code>eflash_loader_40m.bin</code></a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ol>
|
||
<p>This information was derived from <a href="https://github.com/spacemeowx2/blflash/blob/main/blflash/src/main.rs"><code>main.rs</code></a> in <a href="https://github.com/spacemeowx2/blflash"><code>blflash</code></a></p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-pinebook.jpg" alt="PineCone BL602 connected to Pinebook Pro" /></p>
|
||
<p><em>PineCone BL602 connected to Pinebook Pro</em></p>
|
||
<h1 id="whats-next"><a class="doc-anchor" href="#whats-next">§</a>10 What’s Next</h1>
|
||
<p>I had fun reverse-engineering the BL602 source code… And I’m delighted that the BL602 Community is creating really awesome tools like <code>blflash</code>!</p>
|
||
<p>I hope to uncover more BL602 goodies in 2021. Stay tuned!</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/sponsor">Sponsor me a coffee</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/articles/book">Read “The RISC-V BL602 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/flash.md"><code>lupyuen.github.io/src/flash.md</code></a></p>
|
||
<h1 id="notes"><a class="doc-anchor" href="#notes">§</a>11 Notes</h1>
|
||
<ol>
|
||
<li>
|
||
<p>Do all BL602 boards use a jumper or switch for flashing the firmware?</p>
|
||
<p>Yep because all BL602 boards run on the same Boot ROM… Which uses GPIO 8 to decide whether it should go into Flashing Mode.</p>
|
||
<p>Hopefully somebody will create a smarter way to flash BL602 boards and reduce the build-flash-test cycle time.</p>
|
||
<p><strong>UPDATE:</strong> Check out this article…</p>
|
||
<p><a href="https://lupyuen.github.io/articles/auto"><strong>“Auto Flash and Test NuttX on RISC-V BL602”</strong></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://codeberg.org/JF002"><strong>JF</strong></a> reported an interesting problem with his prototype PineDio Stack BL604 V2 board: It fails to flash any firmware.</p>
|
||
<p>(My PineDio Stack V2 flashes OK)</p>
|
||
<p>BLDevCube shows this error…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>{"ErrorCode": "0036","ErrorMsg":"BFLB FLASH WRITE FAIL"}</code></pre></div>
|
||
<p>The engineers at Bouffalo Lab told us…</p>
|
||
<p>“We judge that a hardware error caused XZ work fail, maybe the ram of the chip is faulty.”</p>
|
||
<p>“We have a second way to bypass XZ. There is a configuration file in the /chips/bl602/eflash_loader/ eflash_loader_cfg.ini directory of the Bouffalo Lab DevCube tool.”</p>
|
||
<p>“The configuration file has a config item for decompress_write, Set it from true to false and save configuration file. After the configuration file is modified, you can try program flash again.”</p>
|
||
<p>JF disabled the XZ Decompression and the flashing worked OK.</p>
|
||
<p><img src="https://lupyuen.github.io/images/flash-disablexz.jpg" alt="Disable XZ Decompression in BLDevCube" /></p>
|
||
</li>
|
||
</ol>
|
||
<h1 id="appendix-grant-access-to-usb-uart"><a class="doc-anchor" href="#appendix-grant-access-to-usb-uart">§</a>12 Appendix: Grant Access To USB UART</h1>
|
||
<p><em>(<strong>For Linux Only</strong>)</em></p>
|
||
<p>The USB UART Port <code>/dev/ttyUSB0</code> is <strong>not accessible by normal Linux Users</strong>. (<code>sudo</code> is needed)</p>
|
||
<p>Thus we may see this error when flashing (<code>blflash</code>) or running (<code>screen</code>) BL602 firmware…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>$ blflash flash sdk_app_helloworld.bin --port /dev/ttyUSB0
|
||
|
||
Error: IO error while using serial port:
|
||
Permission denied</code></pre></div>
|
||
<p>To fix this, we need to <strong>add our user to the Linux Group</strong> that has access to the USB UART Port.</p>
|
||
<p>Enter this command to <strong>show the group</strong>…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>ls -g /dev/ttyUSB0</code></pre></div>
|
||
<p>For Debian and Ubuntu: The group is <strong><code>dialout</code></strong>…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>crw-rw---- 1 dialout 188, 0 Feb 16 19:50 /dev/ttyUSB0</code></pre></div>
|
||
<p>For Arch Linux and Manjaro: The group is <strong><code>uucp</code></strong>…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>crw-rw---- 1 uucp 188, 0 Feb 16 19:50 /dev/ttyUSB0</code></pre></div>
|
||
<p>Enter this command to <strong>add our user</strong> to the group…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>## For Debian and Ubuntu:
|
||
sudo usermod -a -G dialout $USER
|
||
|
||
## For Arch Linux and Manjaro:
|
||
sudo usermod -a -G uucp $USER</code></pre></div>
|
||
<p><strong>Logout and login</strong> for the changes to take effect…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>logout</code></pre></div>
|
||
<p>Verify that our user is in the group…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>groups</code></pre></div>
|
||
<p>We should see <code>dialout</code> or <code>uucp</code></p>
|
||
<p>We may now flash (<code>blflash</code>) or run (<code>screen</code>) BL602 firmware. (Without <code>sudo</code>)</p>
|
||
<h1 id="appendix-bl602-flashing-screenshots"><a class="doc-anchor" href="#appendix-bl602-flashing-screenshots">§</a>13 Appendix: BL602 Flashing Screenshots</h1><h2 id="linux-arm64"><a class="doc-anchor" href="#linux-arm64">§</a>13.1 Linux Arm64</h2>
|
||
<p><img src="https://lupyuen.github.io/images/flash-linux.png" alt="Manjaro Linux Arm64 on Pinebook Pro" /></p>
|
||
<p><em>Manjaro Linux Arm64 on Pinebook Pro</em></p>
|
||
<h2 id="macos-catalina"><a class="doc-anchor" href="#macos-catalina">§</a>13.2 macOS Catalina</h2>
|
||
<p><img src="https://lupyuen.github.io/images/flash-macos.png" alt="macOS Catalina" /></p>
|
||
<p><em>macOS Catalina</em></p>
|
||
<h2 id="windows-10"><a class="doc-anchor" href="#windows-10">§</a>13.3 Windows 10</h2>
|
||
<p><img src="https://lupyuen.github.io/images/flash-windows.png" alt="Windows 10" /></p>
|
||
<p><em>Windows 10</em></p>
|
||
<h1 id="appendix-bl602-partition-table"><a class="doc-anchor" href="#appendix-bl602-partition-table">§</a>14 Appendix: BL602 Partition Table</h1>
|
||
<ul>
|
||
<li>
|
||
<p>From <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/partition/partition_cfg_2M.toml"><code>BLOpenFlasher/bl602/ partition/partition_cfg_2M.toml</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p>Will be compiled to binary format <code>bl602/image/partition.bin</code> and flashed to <code>0xE000</code> and <code>0xF000</code></p>
|
||
</li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps2c.png" alt="Compiling the BL602 Partition Table" /></p>
|
||
<p><em>Compiling the BL602 Partition Table</em></p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[pt_table]
|
||
#partition table is 4K in size
|
||
address0 = 0xE000
|
||
address1 = 0xF000
|
||
|
||
[[pt_entry]]
|
||
type = 0
|
||
name = "FW"
|
||
device = 0
|
||
address0 = 0x10000
|
||
size0 = 0xC8000
|
||
address1 = 0xD8000
|
||
size1 = 0x88000
|
||
## compressed image must set len,normal image can left it to 0
|
||
len = 0
|
||
|
||
[[pt_entry]]
|
||
type = 2
|
||
name = "mfg"
|
||
device = 0
|
||
address0 = 0x160000
|
||
size0 = 0x32000
|
||
address1 = 0
|
||
size1 = 0
|
||
## compressed image must set len,normal image can left it to 0
|
||
len = 0
|
||
|
||
[[pt_entry]]
|
||
type = 3
|
||
name = "media"
|
||
device = 0
|
||
address0 = 0x192000
|
||
size0 = 0x57000
|
||
address1 = 0
|
||
size1 = 0
|
||
## compressed image must set len,normal image can left it to 0
|
||
len = 0
|
||
|
||
[[pt_entry]]
|
||
type = 4
|
||
name = "PSM"
|
||
device = 0
|
||
address0 = 0x1E9000
|
||
size0 = 0x8000
|
||
address1 = 0
|
||
size1 = 0
|
||
## compressed image must set len,normal image can left it to 0
|
||
len = 0
|
||
|
||
[[pt_entry]]
|
||
type = 5
|
||
name = "KEY"
|
||
device = 0
|
||
address0 = 0x1F1000
|
||
size0 = 0x2000
|
||
address1 = 0
|
||
size1 = 0
|
||
## compressed image must set len,normal image can left it to 0
|
||
len = 0
|
||
|
||
[[pt_entry]]
|
||
type = 6
|
||
name = "DATA"
|
||
device = 0
|
||
address0 = 0x1F3000
|
||
size0 = 0x5000
|
||
address1 = 0
|
||
size1 = 0
|
||
## compressed image must set len,normal image can left it to 0
|
||
len = 0
|
||
|
||
|
||
[[pt_entry]]
|
||
type = 7
|
||
name = "factory"
|
||
device = 0
|
||
address0 = 0x1F8000
|
||
size0 = 0x7000
|
||
address1 = 0
|
||
size1 = 0
|
||
## compressed image must set len,normal image can left it to 0
|
||
len = 0
|
||
|
||
##if user want to put RF calibration data on flash, uncomment following pt entry
|
||
##[[pt_entry]]
|
||
##type = 8
|
||
##name = "rf_para"
|
||
##device = 0
|
||
##address0 = 0x1FF000
|
||
##size0 = 0x1000
|
||
##address1 = 0
|
||
##size1 = 0
|
||
## compressed image must set len,normal image can left it to 0
|
||
##len = 0</code></pre></div><h1 id="appendix-bl602-device-tree"><a class="doc-anchor" href="#appendix-bl602-device-tree">§</a>15 Appendix: BL602 Device Tree</h1>
|
||
<ul>
|
||
<li>
|
||
<p>From <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts"><code>BLOpenFlasher/bl602/device_tree/ bl_factory_params_IoTKitA_40M.dts</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p>Will be compiled by Python script <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/dts2dtb.py"><code>dts2dtb.py</code></a> to binary format <code>bl602/image/ro_params.dtb</code> and flashed to <code>0x1F8000</code></p>
|
||
</li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps2d.png" alt="Compiling the BL602 Device Tree" /></p>
|
||
<p><em>Compiling the BL602 Device Tree</em></p>
|
||
<div class="example-wrap"><pre class="language-text"><code>/dts-v1/;
|
||
/include/ "bl602_base.dtsi";
|
||
// version: 17
|
||
// last_comp_version: 16
|
||
// boot_cpuid_phys: 0x0
|
||
|
||
/ {
|
||
model = "bl bl602 AVB board";
|
||
compatible = "bl,bl602-sample", "bl,bl602-common";
|
||
#address-cells = <0x1>;
|
||
#size-cells = <0x1>;
|
||
gpio {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
max_num = <40>;
|
||
gpio0 {
|
||
status = "okay";
|
||
pin = <5>;
|
||
feature = "led";
|
||
active = "Hi"; //Hi or Lo
|
||
mode = "blink"; //blink or hearbeat
|
||
time = <100>; //duration for this mode
|
||
};
|
||
gpio1 {
|
||
status = "disable";
|
||
pin = <6>;
|
||
feature = "led";
|
||
active = "Hi"; //Hi or Lo
|
||
mode = "blink"; //blink or hearbeat
|
||
time = <100>; //duration for this mode
|
||
};
|
||
gpio2 {
|
||
status = "okay";
|
||
pin = <2>;
|
||
feature = "button";
|
||
active = "Hi";
|
||
mode = "multipress";
|
||
button {
|
||
debounce = <10>;
|
||
short_press_ms {
|
||
start = <100>;
|
||
end = <3000>;
|
||
kevent = <2>;
|
||
};
|
||
long_press_ms {
|
||
start = <6000>;
|
||
end = <10000>;
|
||
kevent = <3>;
|
||
};
|
||
longlong_press_ms {
|
||
start = <15000>;
|
||
kevent = <4>;
|
||
};
|
||
trig_level = "Hi";
|
||
};
|
||
hbn_use = "disable";
|
||
};
|
||
};
|
||
i2s {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
i2s@40017000 {
|
||
status = "okay";
|
||
compatible = "bl602_i2s";
|
||
reg = <0x40017000 0x100>;
|
||
mclk_only = "okay";
|
||
pin {
|
||
mclk = <11>;
|
||
};
|
||
};
|
||
i2s@40017100 {
|
||
status = "okay";
|
||
compatible = "bl602_i2s";
|
||
reg = <0x40017100 0x100>;
|
||
mclk_only = "disable";
|
||
pin {
|
||
bclk = <12>;
|
||
fs = <29>;
|
||
do = <30>;
|
||
di = <31>;
|
||
};
|
||
};
|
||
};
|
||
i2c {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
i2c@40011000 {
|
||
status = "okay";
|
||
compatible = "bl602_i2c";
|
||
reg = <0x40011000 0x100>;
|
||
pin {
|
||
scl = <32>;
|
||
sda = <13>;
|
||
};
|
||
devices {
|
||
list_addr = <0x18 0x21>;
|
||
list_driver = "i2c_es8311", "i2c_gc0308>";
|
||
};
|
||
};
|
||
i2c@40011100 {
|
||
status = "disable";
|
||
compatible = "bl602_i2c";
|
||
reg = <0x40011100 0x100>;
|
||
pin {
|
||
/*empty here*/
|
||
};
|
||
};
|
||
};
|
||
timer {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
timer@40014000 {
|
||
status = "disable";
|
||
compatible = "bl602_timer";
|
||
reg = <0x40014000 0x100>;
|
||
};
|
||
timer@40014100 {
|
||
status = "disable";
|
||
compatible = "bl602_timer";
|
||
reg = <0x40014100 0x100>;
|
||
};
|
||
};
|
||
pwm {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
pwm@4000A420 {
|
||
status = "okay";
|
||
compatible = "bl602_pwm";
|
||
reg = <0x4000A420 0x20>;
|
||
path = "/dev/pwm0";
|
||
id = <0>;
|
||
pin = <0>;
|
||
freq = <800000>;
|
||
duty = <50>;
|
||
};
|
||
pwm@4000A440 {
|
||
status = "disable";
|
||
reg = <0x4000A440 0x20>;
|
||
path = "/dev/pwm1";
|
||
id = <1>;
|
||
pin = <1>;
|
||
freq = <5000>;
|
||
duty = <50>;
|
||
};
|
||
pwm@4000A460 {
|
||
status = "disable";
|
||
reg = <0x4000A460 0x20>;
|
||
path = "/dev/pwm2";
|
||
id = <2>;
|
||
pin = <2>;
|
||
freq = <5000>;
|
||
duty = <50>;
|
||
};
|
||
pwm@4000A480 {
|
||
status = "disable";
|
||
reg = <0x4000A480 0x20>;
|
||
path = "/dev/pwm3";
|
||
id = <3>;
|
||
pin = <3>;
|
||
freq = <5000>;
|
||
duty = <50>;
|
||
};
|
||
pwm@4000A4A0 {
|
||
status = "disable";
|
||
reg = <0x4000A4A0 0x20>;
|
||
path = "/dev/pwm4";
|
||
id = <4>;
|
||
pin = <4>;
|
||
freq = <5000>;
|
||
duty = <50>;
|
||
};
|
||
};
|
||
ir {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
ctrltype = <0>;
|
||
tx {
|
||
status = "disable";
|
||
pin = <11>; // only support 11
|
||
mode = "NEC"; // NEC、ExtenedNEC、RC5、SWM
|
||
interval = <100>; // ms
|
||
active_mode = "Hi"; //Hi、Lo
|
||
};
|
||
rx {
|
||
status = "okay";
|
||
pin = <12>; // only support 12 13
|
||
mode = "NEC"; // NEC、ExtenedNEC、RC5、SWM
|
||
active_mode = "Hi"; //Hi、Lo
|
||
};
|
||
};
|
||
uart {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
uart@4000A000 {
|
||
status = "okay";
|
||
id = <0>;
|
||
compatible = "bl602_uart";
|
||
path = "/dev/ttyS0";
|
||
baudrate = <2000000>;
|
||
pin {
|
||
rx = <7>;
|
||
tx = <16>;
|
||
};
|
||
buf_size {
|
||
rx_size = <512>;
|
||
tx_size = <512>;
|
||
};
|
||
feature {
|
||
tx = "okay";
|
||
rx = "okay";
|
||
cts = "disable";
|
||
rts = "disable";
|
||
};
|
||
};
|
||
uart@4000A100 {
|
||
status = "okay";
|
||
id = <1>;
|
||
compatible = "bl602_uart";
|
||
path = "/dev/ttyS1";
|
||
baudrate = <115200>;
|
||
pin {
|
||
rx = <3>;
|
||
tx = <4>;
|
||
};
|
||
buf_size {
|
||
rx_size = <512>;
|
||
tx_size = <512>;
|
||
};
|
||
feature {
|
||
tx = "okay";
|
||
rx = "okay";
|
||
cts = "disable";
|
||
rts = "disable";
|
||
};
|
||
};
|
||
};
|
||
spi {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
spi@4000F000 {
|
||
status = "okay"; /* okay disable */
|
||
mode = "master";
|
||
reg = <0x4000F000 0x100>; /* 4KB */
|
||
path = "/dev/spi0";
|
||
port = <0>;
|
||
polar_phase = <1>; /* 0,1,2,3 */
|
||
freq = <6000000>;
|
||
pin {
|
||
clk = <3>;
|
||
cs = <2>;
|
||
mosi = <1>;
|
||
miso = <0>;
|
||
};
|
||
dma_cfg {
|
||
tx_dma_ch = <2>;
|
||
rx_dma_ch = <3>;
|
||
};
|
||
};
|
||
};
|
||
gpip {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
adc_key {
|
||
status = "disable";
|
||
pin = <9>;
|
||
interrupt = <3>;
|
||
key_vol = <0 100 400 300 500>;
|
||
key_pcb = "SW1", "SW2", "SW3", "SW4","SW5";
|
||
key_event = "Usr1", "Usr2", "Start", "Up", "Down";
|
||
key_raw = <1 2 3 4 5>;
|
||
};
|
||
};
|
||
qspi {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
qspi@4000A000 {
|
||
status = "disable";
|
||
reg = <0x4000A000 0x1000>;/* 4KB */
|
||
};
|
||
};
|
||
wifi {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
region {
|
||
country_code = <86>;
|
||
};
|
||
mac {
|
||
mode = "MBF";
|
||
sta_mac_addr = [C8 43 57 82 73 40];
|
||
ap_mac_addr = [C8 43 57 82 73 02];
|
||
};
|
||
sta {
|
||
ssid = "yourssid";
|
||
pwd = "yourapssword";
|
||
auto_connect_enable = <0>;
|
||
};
|
||
ap {
|
||
ssid = "bl_test_005";
|
||
pwd = "12345678";
|
||
ap_channel = <11>;
|
||
auto_chan_detect = "disable";
|
||
};
|
||
brd_rf {
|
||
xtal_mode = "MF";
|
||
xtal = <36 36 0 60 60>;
|
||
/*
|
||
pwr_table = < 4 3 3 186
|
||
4 3 4 176
|
||
4 3 5 167
|
||
3 3 0 159
|
||
3 3 1 149
|
||
3 3 2 140
|
||
3 3 3 129
|
||
3 3 4 119
|
||
3 3 5 110
|
||
2 3 0 101
|
||
2 3 1 91
|
||
2 3 2 82
|
||
2 3 3 72
|
||
2 3 4 62
|
||
2 3 5 52
|
||
1 3 3 10>;
|
||
*/
|
||
pwr_mode = "bf";//B: only use power offset in EFUSE; b: use power offset in EFUSE with incremental mode; F: only use power offset in Flash; f: use power offset in Flash with incremental mode
|
||
pwr_table_11b = <20 20 20 18>;//1Mbps 2Mbps 5.5Mbps 11Mbps
|
||
pwr_table_11g = <18 18 18 18 18 18 14 14>; //6Mbps 9Mbps 12Mbps 18MBps 24Mbps 36Mbps 48Mbps 54Mbps
|
||
pwr_table_11n = <18 18 18 18 18 16 14 14>; //MCS0 MCS1 MCS2 MCS3 MCS4 MCS5 MCS6 MCS7
|
||
pwr_offset = <10 10 10 10 10 10 10 10 10 10 10 10 10 10>;//due to the limit of current DTC, negative value is used. So we work around by adding all the poweroffset with 10. so 8 represents -2; 10 represents 0; 13 represents 3
|
||
channel_div_table = <0x1EEC4EC4 0x1EFCB7CB 0x1F0D20D2 0x1F1D89D8 0x1F2DF2DF 0x1F3E5BE5 0x1F4EC4EC 0x1F5F2DF2 0x1F6F96F9 0x1F800000 0x1F906906 0x1FA0D20D 0x1FB13B13 0x1FD89D89 0x201F81F8>;
|
||
channel_cnt_table = <0xA78A 0xA7E3 0xA83C 0xA895 0xA8ED 0xA946 0xA99F 0xA9F8 0xAA51 0xAAAA 0xAB03 0xAB5C 0xABB5 0xAC8A>;
|
||
lo_fcal_div = <0x56B>;
|
||
};
|
||
};
|
||
bluetooth {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
brd_rf {
|
||
pwr_table_ble = <13>; //range:-3~15dbm; if set -3, please set 253 here
|
||
};
|
||
};
|
||
};</code></pre></div><h1 id="appendix-bl602-efuse-configuration"><a class="doc-anchor" href="#appendix-bl602-efuse-configuration">§</a>16 Appendix: BL602 EFuse Configuration</h1>
|
||
<ul>
|
||
<li>
|
||
<p>From <a href="https://github.com/bouffalolab/BLOpenFlasher/blob/main/bl602/efuse_bootheader/efuse_bootheader_cfg.conf"><code>BLOpenFlasher/bl602/ efuse_bootheader/ efuse_bootheader_cfg.conf</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p>Will be used for transforming Boot2 Bootloader and Firmware Image</p>
|
||
</li>
|
||
<li>
|
||
<p>Also includes the Boot Header Configuration</p>
|
||
</li>
|
||
</ul>
|
||
<p><img src="https://lupyuen.github.io/images/pinecone-flash-steps3.png" alt="Transforming firmware images with BL602 EFuse Configuration" /></p>
|
||
<p><em>Transforming firmware images with BL602 EFuse Configuration</em></p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[EFUSE_CFG]
|
||
########################################################################
|
||
#2bits
|
||
ef_sf_aes_mode = 0
|
||
#2bits
|
||
ef_sboot_sign_mode = 0
|
||
#2bits
|
||
ef_sboot_en = 0
|
||
#2bits
|
||
ef_dbg_jtag_dis = 0
|
||
#4bits
|
||
ef_dbg_mode = 0
|
||
#32bits
|
||
ef_dbg_pwd_low = 0
|
||
#32bits
|
||
ef_dbg_pwd_high = 0
|
||
###################################################################
|
||
ef_key_slot_2_w0 = 0
|
||
ef_key_slot_2_w1 = 0
|
||
ef_key_slot_2_w2 = 0
|
||
ef_key_slot_2_w3 = 0
|
||
ef_key_slot_3_w0 = 0
|
||
ef_key_slot_3_w1 = 0
|
||
ef_key_slot_3_w2 = 0
|
||
ef_key_slot_3_w3 = 0
|
||
ef_key_slot_4_w0 = 0
|
||
ef_key_slot_4_w1 = 0
|
||
ef_key_slot_4_w2 = 0
|
||
ef_key_slot_4_w3 = 0
|
||
|
||
wr_lock_key_slot_4_l = 0
|
||
wr_lock_dbg_pwd = 0
|
||
wr_lock_key_slot_2 = 0
|
||
wr_lock_key_slot_3 = 0
|
||
wr_lock_key_slot_4_h = 0
|
||
rd_lock_dbg_pwd = 0
|
||
rd_lock_key_slot_2 = 0
|
||
rd_lock_key_slot_3 = 0
|
||
rd_lock_key_slot_4 = 0
|
||
|
||
[BOOTHEADER_CFG]
|
||
magic_code = 0x504e4642
|
||
revision = 0x01
|
||
#########################flash cfg#############################
|
||
flashcfg_magic_code = 0x47464346
|
||
#flashcfg_magic_code=0
|
||
io_mode = 4
|
||
cont_read_support = 1
|
||
#0.5T sfctrl_clk_delay=0 sfctrl_clk_invert=3
|
||
#1 T sfctrl_clk_delay=1 sfctrl_clk_invert=1
|
||
#1.5T sfctrl_clk_delay=1 sfctrl_clk_invert=3
|
||
sfctrl_clk_delay = 1
|
||
sfctrl_clk_invert = 0x01
|
||
|
||
reset_en_cmd = 0x66
|
||
reset_cmd = 0x99
|
||
exit_contread_cmd = 0xff
|
||
exit_contread_cmd_size = 3
|
||
|
||
jedecid_cmd = 0x9f
|
||
jedecid_cmd_dmy_clk = 0
|
||
qpi_jedecid_cmd = 0x9f
|
||
qpi_jedecid_dmy_clk = 0
|
||
|
||
sector_size = 4
|
||
mfg_id = 0xef
|
||
page_size = 256
|
||
|
||
chip_erase_cmd = 0xc7
|
||
sector_erase_cmd = 0x20
|
||
blk32k_erase_cmd = 0x52
|
||
blk64k_erase_cmd = 0xd8
|
||
|
||
write_enable_cmd = 0x06
|
||
page_prog_cmd = 0x02
|
||
qpage_prog_cmd = 0x32
|
||
qual_page_prog_addr_mode = 0
|
||
|
||
fast_read_cmd = 0x0b
|
||
fast_read_dmy_clk = 1
|
||
qpi_fast_read_cmd = 0x0b
|
||
qpi_fast_read_dmy_clk = 1
|
||
|
||
fast_read_do_cmd = 0x3b
|
||
fast_read_do_dmy_clk = 1
|
||
fast_read_dio_cmd = 0xbb
|
||
fast_read_dio_dmy_clk = 0
|
||
|
||
fast_read_qo_cmd = 0x6b
|
||
fast_read_qo_dmy_clk = 1
|
||
fast_read_qio_cmd = 0xeb
|
||
fast_read_qio_dmy_clk = 2
|
||
|
||
qpi_fast_read_qio_cmd = 0xeb
|
||
qpi_fast_read_qio_dmy_clk = 2
|
||
qpi_page_prog_cmd = 0x02
|
||
write_vreg_enable_cmd = 0x50
|
||
|
||
wel_reg_index = 0
|
||
qe_reg_index = 1
|
||
busy_reg_index = 0
|
||
wel_bit_pos = 1
|
||
|
||
qe_bit_pos = 1
|
||
busy_bit_pos = 0
|
||
wel_reg_write_len = 2
|
||
wel_reg_read_len = 1
|
||
|
||
qe_reg_write_len = 1
|
||
qe_reg_read_len = 1
|
||
release_power_down = 0xab
|
||
busy_reg_read_len = 1
|
||
|
||
reg_read_cmd0 = 0x05
|
||
reg_read_cmd1 = 0x35
|
||
|
||
reg_write_cmd0 = 0x01
|
||
reg_write_cmd1 = 0x31
|
||
|
||
enter_qpi_cmd = 0x38
|
||
exit_qpi_cmd = 0xff
|
||
cont_read_code = 0x20
|
||
cont_read_exit_code = 0xff
|
||
|
||
burst_wrap_cmd = 0x77
|
||
burst_wrap_dmy_clk = 0x03
|
||
burst_wrap_data_mode = 2
|
||
burst_wrap_code = 0x40
|
||
|
||
de_burst_wrap_cmd = 0x77
|
||
de_burst_wrap_cmd_dmy_clk = 0x03
|
||
de_burst_wrap_code_mode = 2
|
||
de_burst_wrap_code = 0xF0
|
||
|
||
sector_erase_time = 300
|
||
blk32k_erase_time = 1200
|
||
|
||
blk64k_erase_time = 1200
|
||
page_prog_time = 5
|
||
|
||
chip_erase_time = 200000
|
||
power_down_delay = 3
|
||
qe_data = 0
|
||
|
||
flashcfg_crc32 = 0
|
||
|
||
#########################clk cfg####################################
|
||
clkcfg_magic_code = 0x47464350
|
||
#clkcfg_magic_code=0
|
||
|
||
#0:Not use XTAL to set PLL,1:XTAL is 24M ,2:XTAL is 32M ,3:XTAL is 38.4M
|
||
#4:XTAL is 40M,5:XTAL is 26M,6:XTAL is RC32M
|
||
xtal_type = 4
|
||
#0:RC32M,1:XTAL,2:PLL 48M,3:PLL 120M,4:PLL 160M,5:PLL 192M
|
||
pll_clk = 4
|
||
hclk_div = 0
|
||
bclk_div = 1
|
||
#0:120M,1:XCLK(RC32M or XTAL),2:48M,3:80M,4:BCLK,5:96M
|
||
flash_clk_type = 3
|
||
flash_clk_div = 1
|
||
clkcfg_crc32 = 0
|
||
|
||
########################boot cfg####################################
|
||
#1:ECC
|
||
sign = 0
|
||
#1:AES128,2:AES256,3:AES192
|
||
encrypt_type = 0
|
||
key_sel = 0
|
||
no_segment = 1
|
||
cache_enable = 1
|
||
notload_in_bootrom = 0
|
||
aes_region_lock = 0
|
||
cache_way_disable = 0x03
|
||
crc_ignore = 0
|
||
hash_ignore = 0
|
||
|
||
########################image cfg####################################
|
||
#total image len or segment count
|
||
img_len = 0x100
|
||
bootentry = 0
|
||
#img RAM address or flash offset
|
||
img_start = 0x2000
|
||
|
||
#img hash
|
||
hash_0 = 0xdeadbeef
|
||
hash_1 = 0
|
||
hash_2 = 0
|
||
hash_3 = 0
|
||
hash_4 = 0
|
||
hash_5 = 0
|
||
hash_6 = 0
|
||
hash_7 = 0
|
||
|
||
crc32 = 0xdeadbeef</code></pre></div><h1 id="appendix-bldevcube-flashing-log"><a class="doc-anchor" href="#appendix-bldevcube-flashing-log">§</a>17 Appendix: BLDevCube Flashing Log</h1>
|
||
<p>Sample flashing log emitted by <code>bl_iot_sdk/tools/ flash_tool/BLDevCube.exe</code> on Windows…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>[23:01:59.398] - [param]
|
||
interface_type = "Uart"
|
||
comport_uart = "COM5"
|
||
speed_uart = "2000000"
|
||
speed_jlink = "1000"
|
||
bl60x_brd = "IoTKitA"
|
||
bl60x_xtal = "40M"
|
||
aes_key = ""
|
||
aes_iv = ""
|
||
addr = "0x0"
|
||
|
||
[check_box]
|
||
partition_download = true
|
||
boot2_download = true
|
||
bin_download = true
|
||
media_download = false
|
||
use_romfs = false
|
||
mfg_download = false
|
||
ro_params_download = true
|
||
ckb_erase_all = "False"
|
||
encrypt = false
|
||
download_single = false
|
||
|
||
[input_path]
|
||
pt_bin_input = "C:\\pinecone\\bl_iot_sdk\\tools\\flash_tool\\bl602\\partition\\partition_cfg_2M.toml"
|
||
boot2_bin_input = "C:\\pinecone\\bl_iot_sdk\\image_conf\\bl602\\blsp_boot2_release.bin"
|
||
cfg2_bin_input = "C:\\Users\\user\\Downloads\\customer_app.zip\\sdk_app_helloworld\\build_out\\sdk_app_helloworld.bin"
|
||
meida_bin_input = ""
|
||
romfs_dir_input = ""
|
||
mfg_bin_input = ""
|
||
img_bin_input = ""
|
||
[23:01:59.406] - ========= Interface is Uart =========
|
||
[23:01:59.420] - eflash loader bin is eflash_loader_40m.bin
|
||
[23:01:59.421] - ========= chip flash id: ef4015 =========
|
||
[23:01:59.468] - Update flash cfg finished
|
||
[23:01:59.492] - create partition.bin, pt_new == True
|
||
[23:01:59.504] - bl60x_fw_boot_head_gen xtal: 40M
|
||
[23:01:59.509] - Create bootheader using C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini
|
||
[23:01:59.510] - Updating data according to <C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini[BOOTHEADER_CFG]>
|
||
[23:01:59.513] - Created file len:176
|
||
[23:01:59.532] - Create efuse using C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini
|
||
[23:01:59.532] - Updating data according to <C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini[EFUSE_CFG]>
|
||
[23:01:59.535] - Created file len:128
|
||
[23:01:59.570] - ========= sp image create =========
|
||
[23:01:59.642] - Image hash is b'1b80574f36095a60475887c38abcbd10735eb6b2c07f7b119b79fe6755445dfa'
|
||
[23:01:59.643] - Header crc: b'6309dbed'
|
||
[23:01:59.643] - Write flash img
|
||
[23:01:59.677] - bl60x_fw_boot_head_gen xtal: 40M
|
||
[23:01:59.682] - Create bootheader using C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini
|
||
[23:01:59.683] - Updating data according to <C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini[BOOTHEADER_CFG]>
|
||
[23:01:59.685] - Created file len:176
|
||
[23:01:59.693] - Create efuse using C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini
|
||
[23:01:59.694] - Updating data according to <C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\efuse_bootheader/efuse_bootheader_cfg.ini[EFUSE_CFG]>
|
||
[23:01:59.697] - Created file len:128
|
||
[23:01:59.732] - ========= sp image create =========
|
||
[23:01:59.773] - Image hash is b'26d56114b6c744112d88dccf5de778fb40a7feffdd9cb9e0b9c0c299461bf48d'
|
||
[23:01:59.773] - Header crc: b'2a98df4f'
|
||
[23:01:59.774] - Write flash img
|
||
[23:01:59.804] - FW Header is 176, 3920 still needed
|
||
[23:01:59.806] - FW OTA bin header is Done. Len is 4096
|
||
[23:01:59.854] - FW OTA bin is Done. Len is 25216
|
||
[23:01:59.931] - FW OTA xz is Done
|
||
[23:01:59.932] - ========= eflash loader config =========
|
||
[23:01:59.956] - =========C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\device_tree/bl_factory_params_IoTKitA_40M.dtsbl602/device_tree/ro_params.dtb=========
|
||
[23:02:00.260] - Version: bflb_eflash_loader_v1.7.2
|
||
[23:02:00.261] - Program Start
|
||
[23:02:00.261] - option is ['-p', '-t', 'flash', '-d', 'COM5']
|
||
[23:02:00.262] - Config file: C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\eflash_loader/eflash_loader_cfg.ini
|
||
[23:02:00.263] - com device: COM5
|
||
[23:02:00.264] - chiptype: bl602
|
||
[23:02:00.264] - ========= Interface is Uart =========
|
||
[23:02:00.265] - Eflash load helper file: C:\pinecone\bl_iot_sdk\tools\flash_tool\bl602\eflash_loader/eflash_loader_40m.bin
|
||
[23:02:00.265] - ========= load eflash_loader.bin =========
|
||
[23:02:00.265] - Load eflash_loader.bin via uart
|
||
[23:02:00.266] - ========= image load =========
|
||
[23:02:00.541] - tx rx and power off, press the machine!
|
||
[23:02:00.542] - cutoff time is 0.1
|
||
[23:02:00.651] - power on tx and rx
|
||
[23:02:01.463] - reset cnt: 0, reset hold: 0.005, shake hand delay: 0.1
|
||
[23:02:01.464] - clean buf
|
||
[23:02:01.571] - send sync
|
||
[23:02:01.805] - ack is b'4f4b'
|
||
[23:02:01.852] - shake hand success
|
||
[23:02:02.420] - get_boot_info
|
||
[23:02:02.423] - data read is b'010000000000000003000000619dc005b9181d00'
|
||
[23:02:02.424] - sign is 0 encrypt is 0
|
||
[23:02:02.424] - segcnt is 1
|
||
[23:02:02.433] - segdata_len is 21872
|
||
[23:02:02.518] - 4080/21872
|
||
[23:02:02.603] - 8160/21872
|
||
[23:02:02.689] - 12240/21872
|
||
[23:02:02.774] - 16320/21872
|
||
[23:02:02.859] - 20400/21872
|
||
[23:02:02.891] - 21872/21872
|
||
[23:02:02.894] - Run img
|
||
[23:02:03.007] - Load helper bin time cost(ms): 2741.156982421875
|
||
[23:02:03.115] - Program operation
|
||
[23:02:03.116] - ========= flash read jedec ID =========
|
||
[23:02:03.116] - Flash load shake hand
|
||
[23:02:03.117] - clean buf
|
||
[23:02:03.226] - send sync
|
||
[23:02:03.463] - ack is b'4f4b'
|
||
[23:02:03.512] - Read flash jedec ID
|
||
[23:02:03.513] - readdata:
|
||
[23:02:03.514] - b'ef401500'
|
||
[23:02:03.514] - Finished
|
||
[23:02:03.515] - Dealing Index 0
|
||
[23:02:03.516] - ========= programming bl602/img_create/whole_img_boot2.bin to 0x00000000
|
||
[23:02:03.517] - ========= flash load =========
|
||
[23:02:03.518] - ========= flash erase =========
|
||
[23:02:03.519] - Erase flash from 0x0 to 0xb6cf
|
||
[23:02:03.813] - Erase time cost(ms): 292.946044921875
|
||
[23:02:03.855] - Load 2048/46800 {"progress":4}
|
||
Load 4096/46800 {"progress":8}
|
||
[23:02:03.893] - Load 6144/46800 {"progress":13}
|
||
Load 8192/46800 {"progress":17}
|
||
[23:02:03.929] - Load 10240/46800 {"progress":21}
|
||
Load 12288/46800 {"progress":26}
|
||
[23:02:03.966] - Load 14336/46800 {"progress":30}
|
||
Load 16384/46800 {"progress":35}
|
||
[23:02:04.004] - Load 18432/46800 {"progress":39}
|
||
Load 20480/46800 {"progress":43}
|
||
[23:02:04.041] - Load 22528/46800 {"progress":48}
|
||
Load 24576/46800 {"progress":52}
|
||
[23:02:04.079] - Load 26624/46800 {"progress":56}
|
||
Load 28672/46800 {"progress":61}
|
||
[23:02:04.115] - Load 30720/46800 {"progress":65}
|
||
Load 32768/46800 {"progress":70}
|
||
[23:02:04.151] - Load 34816/46800 {"progress":74}
|
||
Load 36864/46800 {"progress":78}
|
||
[23:02:04.187] - Load 38912/46800 {"progress":83}
|
||
Load 40960/46800 {"progress":87}
|
||
[23:02:04.224] - Load 43008/46800 {"progress":91}
|
||
Load 45056/46800 {"progress":96}
|
||
[23:02:04.240] - Load 46800/46800 {"progress":100}
|
||
[23:02:04.241] - Write check
|
||
[23:02:04.243] - Flash load time cost(ms): 428.165283203125
|
||
[23:02:04.243] - Finished
|
||
[23:02:04.245] - Sha caled by host: cc1ce53503cdf01b3ec47225589046bf6e99b3ddba900f8ed9a6201ebb9f323f
|
||
[23:02:04.245] - xip mode Verify
|
||
[23:02:04.259] - Read Sha256/46800
|
||
[23:02:04.260] - Flash xip readsha time cost(ms): 13.030517578125
|
||
[23:02:04.260] - Finished
|
||
[23:02:04.262] - Sha caled by dev: cc1ce53503cdf01b3ec47225589046bf6e99b3ddba900f8ed9a6201ebb9f323f
|
||
[23:02:04.263] - Verify success
|
||
[23:02:04.263] - Dealing Index 1
|
||
[23:02:04.264] - ========= programming bl602/partition/partition.bin to 0xe000
|
||
[23:02:04.264] - ========= flash load =========
|
||
[23:02:04.265] - ========= flash erase =========
|
||
[23:02:04.265] - Erase flash from 0xe000 to 0xe10f
|
||
[23:02:04.301] - Erase time cost(ms): 36.224609375
|
||
[23:02:04.306] - Load 272/272 {"progress":100}
|
||
[23:02:04.306] - Write check
|
||
[23:02:04.309] - Flash load time cost(ms): 7.0009765625
|
||
[23:02:04.309] - Finished
|
||
[23:02:04.310] - Sha caled by host: da4d2fe7d42a71246b0e84d64665b70ad701435f89716c48e6f23ef55340eaa0
|
||
[23:02:04.310] - xip mode Verify
|
||
[23:02:04.320] - Read Sha256/272
|
||
[23:02:04.320] - Flash xip readsha time cost(ms): 8.000732421875
|
||
[23:02:04.320] - Finished
|
||
[23:02:04.322] - Sha caled by dev: da4d2fe7d42a71246b0e84d64665b70ad701435f89716c48e6f23ef55340eaa0
|
||
[23:02:04.323] - Verify success
|
||
[23:02:04.323] - Dealing Index 2
|
||
[23:02:04.324] - ========= programming bl602/partition/partition.bin to 0xf000
|
||
[23:02:04.324] - ========= flash load =========
|
||
[23:02:04.325] - ========= flash erase =========
|
||
[23:02:04.325] - Erase flash from 0xf000 to 0xf10f
|
||
[23:02:04.362] - Erase time cost(ms): 36.013427734375
|
||
[23:02:04.367] - Load 272/272 {"progress":100}
|
||
[23:02:04.368] - Write check
|
||
[23:02:04.370] - Flash load time cost(ms): 6.999755859375
|
||
[23:02:04.370] - Finished
|
||
[23:02:04.371] - Sha caled by host: da4d2fe7d42a71246b0e84d64665b70ad701435f89716c48e6f23ef55340eaa0
|
||
[23:02:04.372] - xip mode Verify
|
||
[23:02:04.382] - Read Sha256/272
|
||
[23:02:04.382] - Flash xip readsha time cost(ms): 8.004150390625
|
||
[23:02:04.382] - Finished
|
||
[23:02:04.384] - Sha caled by dev: da4d2fe7d42a71246b0e84d64665b70ad701435f89716c48e6f23ef55340eaa0
|
||
[23:02:04.385] - Verify success
|
||
[23:02:04.385] - Dealing Index 3
|
||
[23:02:04.386] - ========= programming bl602/img_create/whole_img.bin to 0x10000
|
||
[23:02:04.386] - ========= flash load =========
|
||
[23:02:04.387] - ========= flash erase =========
|
||
[23:02:04.387] - Erase flash from 0x10000 to 0x1627f
|
||
[23:02:04.612] - Erase time cost(ms): 223.555419921875
|
||
[23:02:04.656] - Load 2048/25216 {"progress":8}
|
||
Load 4096/25216 {"progress":16}
|
||
[23:02:04.700] - Load 6144/25216 {"progress":24}
|
||
Load 8192/25216 {"progress":32}
|
||
[23:02:04.743] - Load 10240/25216 {"progress":40}
|
||
Load 12288/25216 {"progress":48}
|
||
[23:02:04.781] - Load 14336/25216 {"progress":56}
|
||
Load 16384/25216 {"progress":64}
|
||
[23:02:04.818] - Load 18432/25216 {"progress":73}
|
||
Load 20480/25216 {"progress":81}
|
||
[23:02:04.856] - Load 22528/25216 {"progress":89}
|
||
Load 24576/25216 {"progress":97}
|
||
[23:02:04.862] - Load 25216/25216 {"progress":100}
|
||
[23:02:04.863] - Write check
|
||
[23:02:04.865] - Flash load time cost(ms): 251.464599609375
|
||
[23:02:04.866] - Finished
|
||
[23:02:04.867] - Sha caled by host: 3507cc26ec24cff845d18eafeb5b50e57e94b443fc539994e79e1f5e8e83a18d
|
||
[23:02:04.867] - xip mode Verify
|
||
[23:02:04.880] - Read Sha256/25216
|
||
[23:02:04.880] - Flash xip readsha time cost(ms): 10.96826171875
|
||
[23:02:04.881] - Finished
|
||
[23:02:04.883] - Sha caled by dev: 3507cc26ec24cff845d18eafeb5b50e57e94b443fc539994e79e1f5e8e83a18d
|
||
[23:02:04.883] - Verify success
|
||
[23:02:04.883] - Dealing Index 4
|
||
[23:02:04.884] - ========= programming bl602/device_tree/ro_params.dtb to 0x1f8000
|
||
[23:02:04.884] - ========= flash load =========
|
||
[23:02:04.885] - ========= flash erase =========
|
||
[23:02:04.885] - Erase flash from 0x1f8000 to 0x1f9626
|
||
[23:02:04.957] - Erase time cost(ms): 71.47705078125
|
||
[23:02:04.993] - Load 2048/5671 {"progress":36}
|
||
Load 4096/5671 {"progress":72}
|
||
[23:02:05.009] - Load 5671/5671 {"progress":100}
|
||
[23:02:05.009] - Write check
|
||
[23:02:05.011] - Flash load time cost(ms): 52.88330078125
|
||
[23:02:05.012] - Finished
|
||
[23:02:05.012] - Sha caled by host: ae42d69b09c2eb134b202b412c00ff175e10b625e2d3c0a2820378bd341926b8
|
||
[23:02:05.013] - xip mode Verify
|
||
[23:02:05.023] - Read Sha256/5671
|
||
[23:02:05.023] - Flash xip readsha time cost(ms): 8.00732421875
|
||
[23:02:05.024] - Finished
|
||
[23:02:05.026] - Sha caled by dev: ae42d69b09c2eb134b202b412c00ff175e10b625e2d3c0a2820378bd341926b8
|
||
[23:02:05.026] - Verify success
|
||
[23:02:05.027] - Program Finished
|
||
[23:02:05.028] - All time cost(ms): 4766.982421875
|
||
[23:02:05.136] - [All Success]</code></pre></div>
|
||
|
||
<!-- 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> |