mirror of
https://github.com/lupyuen/lupyuen.github.io.git
synced 2025-01-13 09:08:30 +08:00
800 lines
No EOL
47 KiB
HTML
800 lines
No EOL
47 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>Debug Rust on PineCone BL602 with VSCode and GDB</title>
|
||
|
||
|
||
<!-- Begin scripts/articles/*-header.html: Article Header for Custom Markdown files processed by rustdoc, like chip8.md -->
|
||
<meta property="og:title"
|
||
content="Debug Rust on PineCone BL602 with VSCode and GDB"
|
||
data-rh="true">
|
||
<meta property="og:description"
|
||
content="How we build and debug Embedded Rust Firmware for PineCone BL602... With VSCode and GDB"
|
||
data-rh="true">
|
||
<meta property="og:image"
|
||
content="https://lupyuen.github.io/images/debug-title.jpg">
|
||
<meta property="og:type"
|
||
content="article" data-rh="true">
|
||
<link rel="canonical" href="https://lupyuen.org/articles/debug.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">Debug Rust on PineCone BL602 with VSCode and GDB</h1>
|
||
<nav id="rustdoc"><ul>
|
||
<li><a href="#install-openocd-rust-and-gdb" title="Install OpenOCD, Rust and GDB">1 Install OpenOCD, Rust and GDB</a><ul>
|
||
<li><a href="#install-openocd" title="Install OpenOCD">1.1 Install OpenOCD</a><ul></ul></li>
|
||
<li><a href="#install-rust" title="Install Rust">1.2 Install Rust</a><ul></ul></li>
|
||
<li><a href="#install-gdb" title="Install GDB">1.3 Install GDB</a><ul></ul></li>
|
||
<li><a href="#check-the-folders" title="Check the folders">1.4 Check the folders</a><ul></ul></li></ul></li>
|
||
<li><a href="#build-rust-firmware" title="Build Rust Firmware">2 Build Rust Firmware</a><ul>
|
||
<li><a href="#rust-firmware-vs-c-firmware" title="Rust Firmware vs C Firmware">2.1 Rust Firmware vs C Firmware</a><ul></ul></li></ul></li>
|
||
<li><a href="#debug-rust-firmware-with-gdb" title="Debug Rust Firmware with GDB">3 Debug Rust Firmware with GDB</a><ul>
|
||
<li><a href="#start-openocd" title="Start OpenOCD">3.1 Start OpenOCD</a><ul></ul></li>
|
||
<li><a href="#start-gdb" title="Start GDB">3.2 Start GDB</a><ul></ul></li>
|
||
<li><a href="#debug-with-gdb" title="Debug with GDB">3.3 Debug with GDB</a><ul></ul></li></ul></li>
|
||
<li><a href="#gdb-script" title="GDB Script">4 GDB Script</a><ul>
|
||
<li><a href="#gdb-and-cargo" title="GDB and cargo">4.1 GDB and cargo</a><ul></ul></li></ul></li>
|
||
<li><a href="#rusty-mastery-and-mystery" title="Rusty Mastery and Mystery">5 Rusty Mastery and Mystery</a><ul>
|
||
<li><a href="#declare-the-main-function" title="Declare the Main Function">5.1 Declare the Main Function</a><ul></ul></li>
|
||
<li><a href="#fetch-the-peripheral-registers" title="Fetch the Peripheral Registers">5.2 Fetch the Peripheral Registers</a><ul></ul></li>
|
||
<li><a href="#get-the-global-register" title="Get the Global Register">5.3 Get the Global Register</a><ul></ul></li>
|
||
<li><a href="#loop-forever" title="Loop Forever">5.4 Loop Forever</a><ul></ul></li>
|
||
<li><a href="#is-something-missing" title="Is Something Missing?">5.5 Is Something Missing?</a><ul></ul></li></ul></li>
|
||
<li><a href="#debug-rust-firmware-with-vscode" title="Debug Rust Firmware with VSCode">6 Debug Rust Firmware with VSCode</a><ul>
|
||
<li><a href="#debugging-features" title="Debugging Features">6.1 Debugging Features</a><ul></ul></li>
|
||
<li><a href="#terminating-openocd" title="Terminating OpenOCD">6.2 Terminating OpenOCD</a><ul></ul></li></ul></li>
|
||
<li><a href="#rust-coders-wanted" title="Rust Coders Wanted">7 Rust Coders Wanted</a><ul>
|
||
<li><a href="#remap-the-uart-port" title="Remap the UART Port">7.1 Remap the UART Port</a><ul></ul></li>
|
||
<li><a href="#create-a-serial-interface" title="Create a Serial Interface">7.2 Create a Serial Interface</a><ul></ul></li>
|
||
<li><a href="#write-to-the-serial-interface" title="Write to the Serial Interface">7.3 Write to the Serial Interface</a><ul></ul></li>
|
||
<li><a href="#boo-boo-on-pinecone" title="Boo-boo on PineCone">7.4 Boo-boo on PineCone</a><ul></ul></li>
|
||
<li><a href="#we-need-more-rust-demos-on-pinecone" title="We need more Rust Demos on PineCone">7.5 We need more Rust Demos on PineCone</a><ul></ul></li></ul></li>
|
||
<li><a href="#whats-next" title="What’s Next">8 What’s Next</a><ul></ul></li>
|
||
<li><a href="#appendix-vscode-settings" title="Appendix: VSCode Settings">9 Appendix: VSCode Settings</a><ul>
|
||
<li><a href="#debugger-settings" title="Debugger Settings">9.1 Debugger Settings</a><ul></ul></li>
|
||
<li><a href="#task-settings" title="Task Settings">9.2 Task Settings</a><ul></ul></li></ul></li></ul></nav><p><img src="https://lupyuen.github.io/images/debug-title.jpg" alt="Debugging PineCone BL602 RISC-V Evaluation Board with Sipeed JTAG Debugger" /></p>
|
||
<p><em>Debugging PineCone BL602 RISC-V Evaluation Board with Sipeed JTAG Debugger</em></p>
|
||
<p>📝 <em>14 Dec 2020</em></p>
|
||
<p>Earlier we took a quick peek at <a href="https://lupyuen.github.io/articles/pinecone"><strong>PineCone BL602 RISC-V Evaluation Board</strong></a>…</p>
|
||
<p>Then we <a href="https://lupyuen.github.io/articles/openocd"><strong>connected PineCone to OpenOCD</strong></a> with a JTAG Debugger…</p>
|
||
<p>Today we’ll learn to build and debug <a href="https://github.com/lupyuen/pinecone-rust"><strong>Rust Firmware for PineCone</strong></a> in two ways…</p>
|
||
<ol>
|
||
<li>
|
||
<p>With the GDB Debugger (text-based)</p>
|
||
</li>
|
||
<li>
|
||
<p>With the VSCode Debugger (graphical-based)</p>
|
||
</li>
|
||
</ol>
|
||
<p>The instructions here should work on Linux, macOS and Windows.</p>
|
||
<p><a href="https://lupyuen.github.io/articles/rust"><strong>UPDATE:</strong> We have a new way to create Rust Firmware with BL602 IoT SDK, check this out</a></p>
|
||
<p><a href="https://youtu.be/b9f2vxYahHY">Watch the Sneak Peek on YouTube</a></p>
|
||
<p><a href="https://github.com/bouffalolab/bl_docs/tree/main/BL602_Openocd&GDB/en">Note: There’s a new doc on BL602, OpenOCD and GDB. Check it out here</a></p>
|
||
<h1 id="install-openocd-rust-and-gdb"><a class="doc-anchor" href="#install-openocd-rust-and-gdb">§</a>1 Install OpenOCD, Rust and GDB</h1><h2 id="install-openocd"><a class="doc-anchor" href="#install-openocd">§</a>1.1 Install OpenOCD</h2>
|
||
<ol>
|
||
<li>
|
||
<p>Follow the instructions in the article…</p>
|
||
<p><a href="https://lupyuen.github.io/articles/openocd">“Connect PineCone BL602 to OpenOCD”</a></p>
|
||
<ul>
|
||
<li>
|
||
<p>Section 4: <a href="https://lupyuen.github.io/articles/openocd#connect-jtag-debugger-to-pinecone">“Connect JTAG Debugger to PineCone”</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Section 5: <a href="https://lupyuen.github.io/articles/openocd#download-and-run-openocd">“Download and run OpenOCD”</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<p>Remember to download <code>bl602-pac</code> and <code>bl602-hal</code></p>
|
||
<p><a href="https://lupyuen.github.io/articles/openocd#download-openocd-script">More details</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Use the Default JTAG Port on PineCone (Without remapping)</p>
|
||
</li>
|
||
<li>
|
||
<p>Copy the extracted xPack OpenOCD folder to the <code>pinecone-rust</code> folder</p>
|
||
<p>Rename it as…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>pinecone-rust/xpack-openocd</code></pre></div></li>
|
||
</ol>
|
||
<h2 id="install-rust"><a class="doc-anchor" href="#install-rust">§</a>1.2 Install Rust</h2>
|
||
<p>Install Rust with support for nightly target <code>riscv32imac-unknown-none-elf</code>….</p>
|
||
<ol>
|
||
<li>
|
||
<p>Browse to <a href="https://rustup.rs/"><code>rustup.rs</code></a></p>
|
||
<p>Follow the instructions to install <code>rustup</code></p>
|
||
</li>
|
||
<li>
|
||
<p>Press Enter to select…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>1) Proceed with installation (default)</code></pre></div></li>
|
||
<li>
|
||
<p><strong>For Linux and macOS:</strong> Open a command prompt and enter…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>source $HOME/.cargo/env
|
||
rustup update
|
||
rustup default nightly
|
||
rustup target add riscv32imac-unknown-none-elf</code></pre></div>
|
||
<p><strong>For Windows:</strong> Enter the above commands in a Windows Command Prompt (not WSL Terminal). Omit the <code>source</code> line.</p>
|
||
</li>
|
||
</ol>
|
||
<h2 id="install-gdb"><a class="doc-anchor" href="#install-gdb">§</a>1.3 Install GDB</h2>
|
||
<p>Now we install <a href="https://xpack.github.io/riscv-none-embed-gcc/"><strong>xPack GCC for RISC-V</strong></a>, which contains the GDB Debugger…</p>
|
||
<ol>
|
||
<li>
|
||
<p>Download GCC from the <a href="https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/tag/v8.3.0-2.3">xPack GCC for RISC-V site</a>…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.3.0-2.3/xpack-riscv-none-embed-gcc-8.3.0-2.3-linux-x64.tar.gz">xPack GCC RISC-V for Linux x64</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.3.0-2.3/xpack-riscv-none-embed-gcc-8.3.0-2.3-linux-arm64.tar.gz">xPack GCC RISC-V for Linux Arm64</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.3.0-2.3/xpack-riscv-none-embed-gcc-8.3.0-2.3-darwin-x64.tar.gz">xPack GCC RISC-V for macOS x64</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.3.0-2.3/xpack-riscv-none-embed-gcc-8.3.0-2.3-win32-x64.zip">xPack GCC RISC-V for Windows x64</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/tag/v8.3.0-2.3">Other builds of xPack GCC RISC-V</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<p>Extract the downloaded archive.</p>
|
||
<p>On Windows: <a href="https://www.7-zip.org/">Use 7-Zip</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Copy the extracted xPack GCC RISC-V folder to the <code>pinecone-rust</code> folder.</p>
|
||
<p>Rename the folder as…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>pinecone-rust/xpack-riscv-none-embed-gcc</code></pre></div></li>
|
||
<li>
|
||
<p>Create a symbolic link for the GDB executable, so that Rust can find it…</p>
|
||
<p><strong>For Linux and macOS:</strong></p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>cd pinecone-rust
|
||
ln -s "$PWD/xpack-riscv-none-embed-gcc/bin/riscv-none-embed-gdb" "$PWD/xpack-riscv-none-embed-gcc/bin/riscv64-unknown-elf-gdb"</code></pre></div>
|
||
<p><strong>For Windows:</strong></p>
|
||
<ul>
|
||
<li>
|
||
<p>In File Explorer, open the folder…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>pinecone-rust\xpack-riscv-none-embed-gcc\bin</code></pre></div></li>
|
||
<li>
|
||
<p>Copy and paste the file <code>riscv-none-embed-gdb.exe</code></p>
|
||
</li>
|
||
<li>
|
||
<p>Rename the copied file as <code>riscv64-unknown-elf-gdb.exe</code></p>
|
||
</li>
|
||
<li>
|
||
<p>Go to Windows Settings and add to <code>PATH</code> the full pathname of the above folder, which will look like this…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>c:\pinecone-rust\xpack-riscv-none-embed-gcc\bin</code></pre></div>
|
||
<p>Change <code>c:\pinecone-rust</code> to the location of the <code>pinecone-rust</code> folder.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ol>
|
||
<h2 id="check-the-folders"><a class="doc-anchor" href="#check-the-folders">§</a>1.4 Check the folders</h2>
|
||
<p>After installing OpenOCD, Rust and GDB, the <code>pinecone-rust</code> folder should look like this…</p>
|
||
<p><img src="https://lupyuen.github.io/images/debug-folders.png" alt="pinecone-rust folder" /></p>
|
||
<p><a href="https://github.com/lupyuen/pinecone-rust/blob/main/README.md">Got problems? Check this doc</a></p>
|
||
<h1 id="build-rust-firmware"><a class="doc-anchor" href="#build-rust-firmware">§</a>2 Build Rust Firmware</h1>
|
||
<p>Let’s build the Rust Firmware…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>cd pinecone-rust
|
||
cargo build</code></pre></div>
|
||
<p>We should see…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code> Compiling autocfg v1.0.1
|
||
Compiling memchr v2.3.4
|
||
Compiling lazy_static v1.4.0
|
||
Compiling regex-syntax v0.6.21
|
||
Compiling semver-parser v0.7.0
|
||
Compiling proc-macro2 v0.4.30
|
||
Compiling unicode-xid v0.1.0
|
||
Compiling rand_core v0.4.2
|
||
Compiling syn v0.15.44
|
||
Compiling bit_field v0.10.1
|
||
Compiling bl602-pac v0.1.0 (/Users/Luppy/pinecone/bl602-pac)
|
||
Compiling bare-metal v1.0.0
|
||
Compiling nb v1.0.0
|
||
Compiling vcell v0.1.2
|
||
Compiling bl602-rust-guide v0.1.0 (/Users/Luppy/pinecone/pinecone-rust)
|
||
Compiling paste v1.0.4
|
||
Compiling r0 v1.0.0
|
||
Compiling panic-halt v0.2.0
|
||
Compiling thread_local v1.0.1
|
||
Compiling rand_core v0.3.1
|
||
Compiling semver v0.9.0
|
||
Compiling embedded-hal v1.0.0-alpha.4 (https://github.com/rust-embedded/embedded-hal#eae6c995)
|
||
Compiling rand v0.5.6
|
||
Compiling num-traits v0.2.14
|
||
Compiling num-integer v0.1.44
|
||
Compiling num-iter v0.1.42
|
||
Compiling num-rational v0.3.2
|
||
Compiling rustc_version v0.2.3
|
||
Compiling aho-corasick v0.7.15
|
||
Compiling bare-metal v0.2.5
|
||
Compiling quote v0.6.13
|
||
Compiling num-complex v0.3.1
|
||
Compiling num v0.3.1
|
||
Compiling embedded-time v0.10.1 (https://github.com/FluenTech/embedded-time#12e78c34)
|
||
Compiling regex v1.4.2
|
||
Compiling riscv-target v0.1.2
|
||
Compiling riscv v0.6.0
|
||
Compiling riscv-rt v0.8.0
|
||
Compiling riscv-rt-macros v0.1.6
|
||
Compiling bl602-hal v0.1.0 (/Users/Luppy/pinecone/bl602-hal)</code></pre></div>
|
||
<p>Ignore these warnings… We’ll cover them in a while.</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>warning: unused imports: `clock::Strict`, `serial::*`
|
||
--> src/main.rs:4:17
|
||
|
|
||
4 | use bl602_hal::{serial::*, pac, prelude::*, clock::Strict};
|
||
| ^^^^^^^^^ ^^^^^^^^^^^^^
|
||
|
|
||
= note: `#[warn(unused_imports)]` on by default
|
||
|
||
warning: unused variable: `parts`
|
||
--> src/main.rs:11:9
|
||
|
|
||
11 | let mut parts = dp.GLB.split();
|
||
| ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_parts`
|
||
|
|
||
= note: `#[warn(unused_variables)]` on by default
|
||
|
||
warning: variable does not need to be mutable
|
||
--> src/main.rs:11:9
|
||
|
|
||
11 | let mut parts = dp.GLB.split();
|
||
| ----^^^^^
|
||
| |
|
||
| help: remove this `mut`
|
||
|
|
||
= note: `#[warn(unused_mut)]` on by default
|
||
|
||
warning: 3 warnings emitted
|
||
|
||
Finished dev [unoptimized + debuginfo] target(s) in 1m 17s</code></pre></div>
|
||
<p>This creates the RISC-V ELF Firmware image for PineCone…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>pinecone-rust/target/riscv32imac-unknown-none-elf/debug/bl602-rust-guide</code></pre></div><h2 id="rust-firmware-vs-c-firmware"><a class="doc-anchor" href="#rust-firmware-vs-c-firmware">§</a>2.1 Rust Firmware vs C Firmware</h2>
|
||
<p><em>Is Rust Firmware any different from the <a href="https://lupyuen.github.io/articles/pinecone">C Firmware</a> that we have seen earlier?</em></p>
|
||
<p>From the Memory Map below, we can see that…</p>
|
||
<ol>
|
||
<li>
|
||
<p>C Firmware runs in the <strong>XIP Flash Memory Region</strong> at <code>0x2300 0000</code></p>
|
||
<p>(XIP means Execute In Place… The firmware code is executed directly from BL602’s Internal Flash Memory, without copying to RAM)</p>
|
||
</li>
|
||
<li>
|
||
<p>Rust Firmware runs in the <strong>Instruction Cache Memory Region</strong> at <code>0x2200 8000</code></p>
|
||
<p>Which is similar to RAM. And probably works better for debugging.</p>
|
||
<p>(The <a href="https://github.com/lupyuen/pinecone-rust/blob/main/memory.x">Build Settings</a> for the Rust Firmware were kindly provided by the <a href="https://github.com/sipeed/bl602-rust-guide">Sipeed BL602 Community</a>)</p>
|
||
</li>
|
||
</ol>
|
||
<p>In the next section we shall use the GDB Debugger to load our Rust Firmware into the cache memory for debugging.</p>
|
||
<p><em>Can we flash Rust Firmware with <code>blflash</code> and other UART flashing tools?</em></p>
|
||
<p>Nope, <code>blflash</code> and other UART flashing tools will not load Rust Firmware into Cache Memory. They will load firmware only to Flash Memory.</p>
|
||
<p>We need a JTAG Debugger for loading Rust Firmware into Cache Memory.</p>
|
||
<p><a href="https://lupyuen.github.io/articles/mynewt#appendix-load-firmware-to-cache-memory-not-flash-memory">More about BL602 Cache Memory vs Flash Memory</a></p>
|
||
<p><img src="https://lupyuen.github.io/images/debug-memory.png" alt="Memory Map of PineCone Firmware: C vs Rust" /></p>
|
||
<p><em>Memory Map of PineCone Firmware: C vs Rust</em></p>
|
||
<h1 id="debug-rust-firmware-with-gdb"><a class="doc-anchor" href="#debug-rust-firmware-with-gdb">§</a>3 Debug Rust Firmware with GDB</h1>
|
||
<p>(If you’re interested only in VSCode debugging, skip to the next section)</p>
|
||
<p>Let’s run the Rust Firmware and debug it with GDB. We’ll need two command prompts: One for OpenOCD and another for GDB.</p>
|
||
<h2 id="start-openocd"><a class="doc-anchor" href="#start-openocd">§</a>3.1 Start OpenOCD</h2>
|
||
<p>At the command prompt, enter…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>cd pinecone-rust
|
||
xpack-openocd/bin/openocd</code></pre></div>
|
||
<p>For Windows: Enter…</p>
|
||
<div class="example-wrap"><pre class="language-cmd"><code>cd pinecone-rust
|
||
xpack-openocd\bin\openocd</code></pre></div>
|
||
<p>We should see OpenOCD connecting to PineCone…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>xPack OpenOCD, x86_64 Open On-Chip Debugger 0.10.0+dev-00378-ge5be992df (2020-06-26-12:31)
|
||
Licensed under GNU GPL v2
|
||
For bug reports, read
|
||
http://openocd.org/doc/doxygen/bugs.html
|
||
Ready for Remote Connections
|
||
Info : clock speed 100 kHz
|
||
Info : JTAG tap: riscv.cpu tap/device found: 0x20000c05 (mfg: 0x602 (<unknown>), part: 0x0000, ver: 0x2)
|
||
Info : datacount=1 progbufsize=2
|
||
Info : Disabling abstract command reads from CSRs.
|
||
Info : Examined RISC-V core; found 1 harts
|
||
Info : hart 0: XLEN=32, misa=0x40801125
|
||
Info : starting gdb server for riscv.cpu.0 on 3333
|
||
Info : Listening on port 3333 for gdb connections
|
||
Info : JTAG tap: riscv.cpu tap/device found: 0x20000c05 (mfg: 0x602 (<unknown>), part: 0x0000, ver: 0x2)
|
||
reset-assert-pre
|
||
reset-deassert-post
|
||
Info : Disabling abstract command writes to CSRs.
|
||
reset-init
|
||
Info : Listening on port 6666 for tcl connections
|
||
Info : Listening on port 4444 for telnet connections</code></pre></div>
|
||
<p>Keep OpenOCD running as we start GDB…</p>
|
||
<h2 id="start-gdb"><a class="doc-anchor" href="#start-gdb">§</a>3.2 Start GDB</h2>
|
||
<p>Open another command prompt. Enter…</p>
|
||
<div class="example-wrap"><pre class="language-bash"><code>cd pinecone-rust
|
||
export PATH="$PWD/xpack-riscv-none-embed-gcc/bin:$PATH"
|
||
cargo run</code></pre></div>
|
||
<p>For Windows: Omit the line <code>export PATH</code></p>
|
||
<p>We should see…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code> Finished dev [unoptimized + debuginfo] target(s) in 0.08s
|
||
Running `riscv64-unknown-elf-gdb -q -x openocd.gdb target/riscv32imac-unknown-none-elf/debug/bl602-rust-guide`
|
||
Reading symbols from target/riscv32imac-unknown-none-elf/debug/bl602-rust-guide...
|
||
0x21000000 in ?? ()
|
||
Loading section .text, size 0x22b0 lma 0x22008000
|
||
Loading section .rodata, size 0x5d8 lma 0x2200a2b0
|
||
Start address 0x22008000, load size 10376
|
||
Transfer rate: 2 KB/sec, 5188 bytes/write.</code></pre></div>
|
||
<p>GDB has loaded our Rust Firmware into PineCone’s cache memory. PineCone starts running our firmware…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Breakpoint 1 at 0x22008000: file asm.S, line 27.
|
||
|
||
Breakpoint 1, _start () at asm.S:27
|
||
27 asm.S: No such file or directory.</code></pre></div>
|
||
<p>GDB has paused the firmware execution at a Breakpoint in our code. (We’ll see this Breakpoint shortly)</p>
|
||
<h2 id="debug-with-gdb"><a class="doc-anchor" href="#debug-with-gdb">§</a>3.3 Debug with GDB</h2>
|
||
<p>At the GDB prompt, enter…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>break main
|
||
continue</code></pre></div>
|
||
<p>This tells GDB to set a Breakpoint at the <code>main</code> function in Rust. And continue execution until we hit the Breakpoint.</p>
|
||
<p>We’ll see…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>(gdb) break main
|
||
Breakpoint 2 at 0x2200924e: file src/main.rs, line 10.
|
||
(gdb) continue
|
||
Continuing.
|
||
|
||
Breakpoint 2, main () at src/main.rs:10
|
||
10 let dp = pac::Peripherals::take().unwrap();</code></pre></div>
|
||
<p>GDB has paused execution at the <code>main</code> function in Rust.</p>
|
||
<ul>
|
||
<li><a href="https://github.com/lupyuen/pinecone-rust/blob/main/src/main.rs">Rust Source File</a></li>
|
||
</ul>
|
||
<p>Enter <code>next</code> to resume execution until the next line…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>(gdb) next
|
||
11 let mut parts = dp.GLB.split();
|
||
(gdb) bt
|
||
#0 main () at src/main.rs:11</code></pre></div>
|
||
<p>The <code>bt</code> command shows us the Stack Trace and local variables.</p>
|
||
<ul>
|
||
<li><a href="https://youtu.be/A54Agz35vfk">Watch on YouTube</a></li>
|
||
</ul>
|
||
<p>Yep we’re now debugging our Rust Firmware with GDB! Check out the GDB docs for more debugging commands…</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://sourceware.org/gdb/current/onlinedocs/gdb/index.html">Debugging with GDB</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://gist.github.com/rkubik/b96c23bd8ed58333de37f2b8cd052c30">GDB Cheat Sheet</a></p>
|
||
</li>
|
||
</ul>
|
||
<p>In OpenOCD we’ll see this warning… Just ignore it</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>Info : accepting 'gdb' connection on tcp/3333
|
||
Info : Disabling abstract command reads from FPRs.
|
||
Warn : negative reply, retrying
|
||
Warn : negative acknowledgment, but no packet pending</code></pre></div><h1 id="gdb-script"><a class="doc-anchor" href="#gdb-script">§</a>4 GDB Script</h1>
|
||
<p><em>What’s driving GDB? How does GDB know how to do the things that it did?</em></p>
|
||
<p>That’s the purpose of the GDB Script. Let’s look inside <a href="https://github.com/lupyuen/pinecone-rust/blob/main/openocd.gdb"><code>openocd.gdb</code></a>…</p>
|
||
<ol>
|
||
<li>
|
||
<p>GDB doesn’t talk to PineCone natively… But GDB can talk to PineCone through OpenOCD.</p>
|
||
<p>This command tells GDB to talk to OpenOCD through the TCP port <code>localhost:3333</code>…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>target extended-remote :3333</code></pre></div></li>
|
||
<li>
|
||
<p>The Rust Compiler will mangle up most function names. The function name <code>riscv::interrupt::enable</code> becomes this…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>_ZN5riscv9interrupt6enable17ha2fdcd71882d698eE</code></pre></div>
|
||
<p>Here’s how we display the dismangled function names…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code># Print demangled symbols
|
||
set print asm-demangle on</code></pre></div></li>
|
||
<li>
|
||
<p>We set a Backtrace Limit that we don’t get stuck in a loop while displaying the Stack Trace (the <code>bt</code> command)…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code># Set backtrace limit to not have infinite backtrace loops
|
||
set backtrace limit 32</code></pre></div></li>
|
||
<li>
|
||
<p>We tell GDB about the Memory Regions on BL602, and whether they are Read-Write (<code>rw</code>) or Read-Only (<code>ro</code>)…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>mem 0x22008000 0x22014000 rw
|
||
mem 0x42008000 0x42014000 rw
|
||
mem 0x22014000 0x22020000 rw
|
||
mem 0x42014000 0x42020000 rw
|
||
mem 0x22020000 0x22030000 rw
|
||
mem 0x42020000 0x42030000 rw
|
||
mem 0x22030000 0x2204C000 rw
|
||
mem 0x42030000 0x4204C000 rw
|
||
mem 0x23000000 0x23400000 ro</code></pre></div>
|
||
<p>Refer to <a href="https://github.com/bouffalolab/bl_docs/blob/main/BL602_RM/en/BL602_BL604_RM_1.2_en.pdf">BL602 Reference Manual</a>, Section 1.3 “Function Description”, Pages 17 to 19.</p>
|
||
</li>
|
||
<li>
|
||
<p>We load the Rust Firmware into BL602’s Instruction Cache Memory…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>load</code></pre></div></li>
|
||
<li>
|
||
<p>We create a Breakpoint at the function <code>_start</code>. This function is the first thing that runs when we start the firmware…</p>
|
||
<div class="example-wrap"><pre class="language-text"><code>break _start</code></pre></div>
|
||
<p><a href="https://github.com/rust-embedded/riscv-rt/blob/master/asm.S">Source code for <code>_start</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p>Finally we step into the first RISC-V instruction in our firmware… And pause the execution</p>
|
||
<div class="example-wrap"><pre class="language-text"><code># Start the process but immediately halt the processor
|
||
stepi</code></pre></div></li>
|
||
</ol>
|
||
<h2 id="gdb-and-cargo"><a class="doc-anchor" href="#gdb-and-cargo">§</a>4.1 GDB and cargo</h2>
|
||
<p><em>How is the Rust Tool <code>cargo</code> configured to launch GDB?</em></p>
|
||
<p><code>cargo</code> is configured through <a href="https://github.com/lupyuen/pinecone-rust/blob/main/.cargo/config.toml"><code>.cargo/config.toml</code></a>…</p>
|
||
<div class="example-wrap"><pre class="language-yaml"><code>[target.riscv32imac-unknown-none-elf]
|
||
rustflags = [
|
||
"-C", "link-arg=-Tmemory.x",
|
||
"-C", "link-arg=-Tlink.x",
|
||
]
|
||
runner = "riscv64-unknown-elf-gdb -q -x openocd.gdb"
|
||
## runner = "riscv32-unknown-elf-gdb -q -x openocd.gdb"
|
||
|
||
[build]
|
||
target = "riscv32imac-unknown-none-elf"</code></pre></div>
|
||
<p>We see that <code>cargo</code> has been configured to launch <code>riscv64-unknown-elf-gdb</code> with the GDB Script <a href="https://github.com/lupyuen/pinecone-rust/blob/main/openocd.gdb"><code>openocd.gdb</code></a>. The GDB Script loads our Rust Firmware to PineCone and starts debugging.</p>
|
||
<p>Also, <code>cargo</code> has been configured to produce Rust Firmware that uses the Memory Map Layout specified by <a href="https://github.com/lupyuen/pinecone-rust/blob/main/memory.x"><code>memory.x</code></a>.</p>
|
||
<p><em>What about the OpenOCD Script?</em></p>
|
||
<p>The OpenOCD Script <a href="https://github.com/lupyuen/pinecone-rust/blob/main/openocd.cfg"><code>openocd.cfg</code></a> has been covered in our previous article…</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/articles/openocd">“Connect PineCone BL602 to OpenOCD”</a></li>
|
||
</ul>
|
||
<p><a href="https://github.com/lupyuen/pinecone-rust/blob/main/openocd.gdb"><code>openocd.gdb</code></a> and <a href="https://github.com/lupyuen/pinecone-rust/blob/main/openocd.cfg"><code>openocd.cfg</code></a> were graciously provided by the <a href="https://github.com/sipeed/bl602-rust-guide">Sipeed BL602 Community</a></p>
|
||
<h1 id="rusty-mastery-and-mystery"><a class="doc-anchor" href="#rusty-mastery-and-mystery">§</a>5 Rusty Mastery and Mystery</h1>
|
||
<p>Before we talk about VSCode Debugging, let’s study the Source Code for our Rust Firmware: <a href="https://github.com/lupyuen/pinecone-rust/blob/main/src/main.rs">src/main.rs</a></p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="attr">#[riscv_rt::entry]
|
||
</span><span class="kw">fn </span>main() -> ! {
|
||
<span class="kw">let </span>dp = pac::Peripherals::take().unwrap();
|
||
<span class="kw">let </span><span class="kw-2">mut </span>parts = dp.GLB.split();
|
||
...
|
||
<span class="comment">// Loop forever
|
||
</span><span class="kw">loop </span>{}
|
||
} </code></pre></div>
|
||
<p>Even folks who have mastered Rust will find Embedded Rust a little strange… Let’s zoom into the code, line by line.</p>
|
||
<h2 id="declare-the-main-function"><a class="doc-anchor" href="#declare-the-main-function">§</a>5.1 Declare the Main Function</h2>
|
||
<p>At the top we have a Rust Attribute that declares the Entry Function for our RISC-V firmware…</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="attr">#[riscv_rt::entry]</span></code></pre></div>
|
||
<p>Followed by the declaration of our Entry Function <code>main</code>…</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">fn </span>main() -> ! {</code></pre></div>
|
||
<p>This means that our Rust Function <code>main</code> will be called when the firmware starts, after initialising the registers and RAM. (<a href="https://github.com/rust-embedded/riscv-rt/blob/master/asm.S">More details</a>)</p>
|
||
<p>(The return type “<code>-> !</code>” means that the function will loop forever, never returning)</p>
|
||
<h2 id="fetch-the-peripheral-registers"><a class="doc-anchor" href="#fetch-the-peripheral-registers">§</a>5.2 Fetch the Peripheral Registers</h2>
|
||
<p>Our BL602 Microcontroller supports multiple Peripheral Functions: Timer, UART, I2C, SPI, PWM, …</p>
|
||
<p>Here’s how we fetch the Peripheral Registers that control the Peripheral Functions…</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">let </span>dp = pac::Peripherals::take().unwrap();</code></pre></div>
|
||
<p><code>pac</code> refers to the Peripheral Access Crate for BL602. It exposes <code>Peripherals</code>, the Peripheral Registers for BL602.</p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/pinecone-rust/bl602_pac/">More about BL602 Peripheral Access Crate</a></li>
|
||
</ul>
|
||
<p><em>Why the <code>take</code> and <code>unwrap</code>?</em></p>
|
||
<p>Rust is known for its Code Safety in Systems Programming.</p>
|
||
<p><code>take</code> + <code>unwrap</code> is a common pattern in Embedded Rust to ensure that we access the Hardware Registers safely.</p>
|
||
<ul>
|
||
<li><a href="https://rust-embedded.github.io/book/start/registers.html">More about Embedded Rust Registers</a></li>
|
||
</ul>
|
||
<h2 id="get-the-global-register"><a class="doc-anchor" href="#get-the-global-register">§</a>5.3 Get the Global Register</h2>
|
||
<p>BL602’s Global Register (GLB) controls the global settings of the Bl602 Microcontroller.</p>
|
||
<p>It provides settings for Clock Management, Reset Management, Bus Management, Memory Management and GPIO Management.</p>
|
||
<p>We fetch the Global Register (and its components) from the Peripheral Registers like so…</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">let </span><span class="kw-2">mut </span>parts = dp.GLB.split();</code></pre></div>
|
||
<ul>
|
||
<li>Refer to <a href="https://github.com/bouffalolab/bl_docs/blob/main/BL602_RM/en/BL602_BL604_RM_1.2_en.pdf">BL602 Reference Manual</a>, Section 3 “GLB”, Page 24.</li>
|
||
</ul>
|
||
<h2 id="loop-forever"><a class="doc-anchor" href="#loop-forever">§</a>5.4 Loop Forever</h2>
|
||
<p>Our firmware should never terminate… It should loop forever handling events.</p>
|
||
<p>For now we’ll use an empty loop…</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="comment">// Loop forever
|
||
</span><span class="kw">loop </span>{}</code></pre></div>
|
||
<h2 id="is-something-missing"><a class="doc-anchor" href="#is-something-missing">§</a>5.5 Is Something Missing?</h2>
|
||
<p><em>Where’s the rest of the Rust code?</em></p>
|
||
<p>This program was originally created for Sipeed’s BL602 Board… But some parts don’t work on PineCone and have been commented out. (Hence the compiler warnings)</p>
|
||
<p>We’ll discuss this mystery in a while.</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/pinecone-rust/">Rust Documentation for PineCone</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://rust-embedded.github.io/book/">Rust Embedded Book</a></p>
|
||
</li>
|
||
</ul>
|
||
<h1 id="debug-rust-firmware-with-vscode"><a class="doc-anchor" href="#debug-rust-firmware-with-vscode">§</a>6 Debug Rust Firmware with VSCode</h1>
|
||
<p>GDB Debugging feels One Dimensional… An endless stream of text. Fortunately we got Two Dimensional graphical debugging: <a href="https://code.visualstudio.com/"><strong>VSCode</strong></a>!</p>
|
||
<ol>
|
||
<li>
|
||
<p>Launch VSCode</p>
|
||
</li>
|
||
<li>
|
||
<p>Click <strong><code>File → Open</code></strong></p>
|
||
<p>Select the folder <strong><code>pinecone-rust</code></strong></p>
|
||
</li>
|
||
<li>
|
||
<p>Click <strong><code>Terminal → Run Build Task</code></strong></p>
|
||
<p>This builds the Rust Firmware. The RISC-V ELF Firmware image is generated here…</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code>pinecone-rust/target/riscv32imac-unknown-none-elf/debug/bl602-rust-guide</code></pre></div>
|
||
<p>This step also terminates any OpenOCD processes that are running. (Linux and macOS only)</p>
|
||
</li>
|
||
<li>
|
||
<p>Click <strong><code>Run → Start Debugging</code></strong></p>
|
||
<p>The debugger loads our Rust Firmware to PineCone’s Cache Memory and begins execution.</p>
|
||
<p>Click <strong><code>View → Debug Console</code></strong> to view the Debug Console. GDB messages will be shown here.</p>
|
||
</li>
|
||
<li>
|
||
<p>The debugger pauses execution at the first line of the <code>main</code> function</p>
|
||
<p>We should see the screen below…</p>
|
||
<p><a href="https://youtu.be/b9f2vxYahHY">Watch on YouTube</a></p>
|
||
</li>
|
||
</ol>
|
||
<p><img src="https://lupyuen.github.io/images/debug-vscode.png" alt="VSCode Debugger with Rust Firmware for PineCone BL602" /></p>
|
||
<p><em>VSCode Debugger with Rust Firmware for PineCone BL602</em></p>
|
||
<h2 id="debugging-features"><a class="doc-anchor" href="#debugging-features">§</a>6.1 Debugging Features</h2>
|
||
<p>We may use these features for debugging our Rust Firmware…</p>
|
||
<ol>
|
||
<li>
|
||
<p><strong>Variables</strong> (Left Top Pane): Inspect global and local variables</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Watch</strong> (Left Centre): Show the value of expressions</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Call Stack</strong> (Left Bottom): Navigate the stack trace and its variables</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Debug Console</strong> (Centre): Enter GDB commands here</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Debug Toolbar</strong> (Top Right): Continue / Pause, Step Over, Step Into, Step Out, Restart, Stop</p>
|
||
</li>
|
||
<li>
|
||
<p>To set a <strong>Breakpoint</strong>, click the Gutter Column at the left of the source code</p>
|
||
</li>
|
||
<li>
|
||
<p>When we’re done with debugging, click the Stop button in the Debug Toolbar at top right</p>
|
||
</li>
|
||
</ol>
|
||
<p><a href="https://youtu.be/b9f2vxYahHY">Watch on YouTube</a></p>
|
||
<p><a href="https://code.visualstudio.com/docs/editor/debugging">More about VSCode Debugger</a></p>
|
||
<h2 id="terminating-openocd"><a class="doc-anchor" href="#terminating-openocd">§</a>6.2 Terminating OpenOCD</h2>
|
||
<p>Before we start a new debugging session with <strong><code>Run → Start Debugging</code></strong>…</p>
|
||
<p><em>We must always click <strong><code>Terminal → Run Build Task</code></strong> first!</em></p>
|
||
<p>That’s because stopping the debugger will leave OpenOCD running (and locking up the connection to PineCone).</p>
|
||
<p>Clicking <strong><code>Run Build Task</code></strong> will terminate the OpenOCD task, so that the next debugging session can restart OpenOCD successfully.</p>
|
||
<p>For Windows: Sorry we need to terminate the OpenOCD task manually with the Task Manager.</p>
|
||
<p>In case of OpenOCD problems, check the OpenOCD log file…</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code>pinecone-rust/openocd.log</code></pre></div>
|
||
<p>For details on the VSCode settings, check the section “Appendix: VSCode Settings” below.</p>
|
||
<h1 id="rust-coders-wanted"><a class="doc-anchor" href="#rust-coders-wanted">§</a>7 Rust Coders Wanted</h1>
|
||
<p>Earlier we talked about some parts of the Rust Firmware code that don’t work on PineCone. (Because the code was created for Sipeed’s BL602 Board)</p>
|
||
<p>Let’s look at the sus parts: <a href="https://github.com/lupyuen/pinecone-rust/blob/main/src/main.rs#L14-L36"><code>src/main.rs</code></a></p>
|
||
<h2 id="remap-the-uart-port"><a class="doc-anchor" href="#remap-the-uart-port">§</a>7.1 Remap the UART Port</h2>
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="comment">// Enable clock
|
||
</span><span class="kw">let </span>clocks = Strict::new()
|
||
.freeze(<span class="kw-2">&mut </span>parts.clk_cfg);
|
||
<span class="kw">let </span>pin16 = parts.pin16.into_uart_sig0();
|
||
<span class="kw">let </span>pin7 = parts.pin7.into_uart_sig7();
|
||
<span class="kw">let </span>mux0 = parts.uart_mux0.into_uart0_tx();
|
||
<span class="kw">let </span>mux7 = parts.uart_mux7.into_uart0_rx();</code></pre></div>
|
||
<p>This code seems to be remapping pins IO 7 and IO 16 to UART Port 0. (Because BL602 allows us to remap any IO Pin to any Peripheral Function)</p>
|
||
<p>See <a href="https://github.com/bouffalolab/bl_docs/blob/main/BL602_RM/en/BL602_BL604_RM_1.2_en.pdf">BL602 Reference Manual</a>, Section 3.2.8 “GPIO Function”, Page 27</p>
|
||
<h2 id="create-a-serial-interface"><a class="doc-anchor" href="#create-a-serial-interface">§</a>7.2 Create a Serial Interface</h2>
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">let </span><span class="kw-2">mut </span>serial = Serial::uart0(
|
||
dp.UART,
|
||
Config::default().baudrate(<span class="number">20000</span>.Bd()),
|
||
((pin16, mux0), (pin7, mux7)),
|
||
clocks
|
||
);</code></pre></div>
|
||
<p>This code creates a Serial Interface based on UART Port 0 with the remapped pins.</p>
|
||
<p><code>Serial</code> is defined in the <a href="https://lupyuen.github.io/pinecone-rust/bl602_hal/">BL602 Hardware Abstraction Layer</a></p>
|
||
<h2 id="write-to-the-serial-interface"><a class="doc-anchor" href="#write-to-the-serial-interface">§</a>7.3 Write to the Serial Interface</h2>
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">loop </span>{
|
||
serial.try_write(<span class="string">b'R'</span>).ok();
|
||
serial.try_flush().ok();
|
||
serial.try_write(<span class="string">b'U'</span>).ok();
|
||
serial.try_flush().ok();
|
||
serial.try_write(<span class="string">b'S'</span>).ok();
|
||
serial.try_flush().ok();
|
||
serial.try_write(<span class="string">b'T'</span>).ok();
|
||
serial.try_flush().ok();
|
||
}</code></pre></div>
|
||
<p>This code loops forever, writing the characters <code>RUST</code> to the Serial Interface.</p>
|
||
<h2 id="boo-boo-on-pinecone"><a class="doc-anchor" href="#boo-boo-on-pinecone">§</a>7.4 Boo-boo on PineCone</h2>
|
||
<p><em>What happens when we run the above code on PineCone?</em></p>
|
||
<p>The GDB Debugger shows an error while executing the UART remapping code above. The code seems to terminate JTAG debugging connection, not sure why.</p>
|
||
<p><em>If there are any Brave Souls out there… Please rebuild the firmware with these chunks of code uncommented, step through with the debugger, and tell us what went wrong!</em></p>
|
||
<h2 id="we-need-more-rust-demos-on-pinecone"><a class="doc-anchor" href="#we-need-more-rust-demos-on-pinecone">§</a>7.5 We need more Rust Demos on PineCone</h2>
|
||
<p><a href="https://github.com/9names/bl602-rust-example"><strong>UPDATE: Check out this Rust Firmware that runs in XIP Flash Memory instead of Cache Memory</strong></a></p>
|
||
<p>The Sipeed BL602 Community has provided two more Rust Demos…</p>
|
||
<ul>
|
||
<li>
|
||
<p>GPIO Blinky Demo: <a href="https://github.com/lupyuen/pinecone-rust/blob/main/examples/bl602-gpio-blinky.rs"><code>examples/bl602-gpio-blinky.rs</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p>Serial Demo: <a href="https://github.com/lupyuen/pinecone-rust/blob/main/examples/bl602-serial.rs"><code>examples/bl602-serial.rs</code></a></p>
|
||
</li>
|
||
</ul>
|
||
<p>But they won’t work on PineCone due to the board differences. Thus we need to create our own Rust Demos for PineCone…</p>
|
||
<p><strong>Perhaps blinking the onboard RGB LED through the PWM Port?</strong></p>
|
||
<ul>
|
||
<li><a href="https://lupyuen.github.io/pinecone-rust/bl602_pac/pwm/index.html">PWM docs in the BL602 Peripheral Access Crate</a></li>
|
||
</ul>
|
||
<p>Note that PineCone’s LED is connected to the same pins as the JTAG Port… So we need to remap the JTAG Port to other pins. (Which may complicate the debugging)</p>
|
||
<ul>
|
||
<li>See <a href="https://lupyuen.github.io/articles/openocd">“Connect PineCone BL602 to OpenOCD”</a>, Section 8: <a href="https://lupyuen.github.io/articles/openocd#remap-the-jtag-port">“Remap the JTAG Port”</a></li>
|
||
</ul>
|
||
<p><em>Can YOU create a Rust Demo that blinks PineCone’s RGB LED via PWM?</em></p>
|
||
<p><em><a href="https://github.com/lupyuen/pinecone-rust">Please submit a Pull Request!</a> Thank you 🙏</em></p>
|
||
<p><img src="https://lupyuen.github.io/images/debug-pool.jpg" alt="Poolside Debugging with PineCone BL602 RISC-V Evaluation Board" /></p>
|
||
<p><em>Poolside Debugging with PineCone BL602 RISC-V Evaluation Board</em></p>
|
||
<h1 id="whats-next"><a class="doc-anchor" href="#whats-next">§</a>8 What’s Next</h1>
|
||
<p>Now that we have GDB and VSCode Debuggers working with Rust Firmware on PineCone… It’s time for me to start something that I care deeply about…</p>
|
||
<p><strong>Porting <a href="http://mynewt.apache.org/">Apache Mynewt RTOS</a> to PineCone</strong></p>
|
||
<p><em>And yes it shall support Rust too!</em></p>
|
||
<p>Read about it here…</p>
|
||
<ul>
|
||
<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/articles/sponsor">Sponsor me a coffee</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io">Check out my articles</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/rss.xml">RSS Feed</a></p>
|
||
</li>
|
||
</ul>
|
||
<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/debug.md"><code>lupyuen.github.io/src/debug.md</code></a></p>
|
||
<h1 id="appendix-vscode-settings"><a class="doc-anchor" href="#appendix-vscode-settings">§</a>9 Appendix: VSCode Settings</h1><h2 id="debugger-settings"><a class="doc-anchor" href="#debugger-settings">§</a>9.1 Debugger Settings</h2>
|
||
<p>The VSCode Debugger Settings may be found in <a href="https://github.com/lupyuen/pinecone-rust/blob/main/.vscode/launch.json"><code>.vscode/launch.json</code></a></p>
|
||
<p>This file defines…</p>
|
||
<ul>
|
||
<li>
|
||
<p>Firmware Path (<code>target</code>)</p>
|
||
</li>
|
||
<li>
|
||
<p>GDB Path (<code>gdbpath</code>)</p>
|
||
</li>
|
||
<li>
|
||
<p>OpenOCD Path (in <code>autorun</code>, after <code>target remote</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<div class="example-wrap"><pre class="language-json"><code>{
|
||
// VSCode Debugger Config for PineCone BL602
|
||
"version": "0.2.0",
|
||
"configurations": [
|
||
{
|
||
"name": "BL602",
|
||
"type": "gdb",
|
||
"request": "launch",
|
||
// Application Executable to be flashed before debugging
|
||
"target": "${workspaceRoot}/target/riscv32imac-unknown-none-elf/debug/bl602-rust-guide",
|
||
"cwd": "${workspaceRoot}",
|
||
"gdbpath": "${workspaceRoot}/xpack-riscv-none-embed-gcc/bin/riscv-none-embed-gdb",
|
||
"valuesFormatting": "parseText",
|
||
"autorun": [
|
||
// Before loading the Application, run these gdb commands.
|
||
// Set timeout for executing openocd commands.
|
||
"set remotetimeout 600",
|
||
|
||
// This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
|
||
"set breakpoint pending on",
|
||
|
||
// Set breakpoints
|
||
"break main", // Break at main()
|
||
|
||
// Launch OpenOCD. Based on https://www.justinmklam.com/posts/2017/10/vscode-debugger-setup/
|
||
"target remote | xpack-openocd/bin/openocd -c \"gdb_port pipe; log_output openocd.log\" -f openocd.cfg ",
|
||
|
||
// Load the program into cache memory
|
||
"load",
|
||
|
||
// Run the program until we hit the main() breakpoint
|
||
"continue",
|
||
]
|
||
}
|
||
]
|
||
}</code></pre></div><h2 id="task-settings"><a class="doc-anchor" href="#task-settings">§</a>9.2 Task Settings</h2>
|
||
<p>The VSCode Task Settings may be found in <a href="https://github.com/lupyuen/pinecone-rust/blob/main/.vscode/tasks.json"><code>.vscode/tasks.json</code></a></p>
|
||
<p>This file defines the VSCode Task for building the Rust Firmware…</p>
|
||
<div class="example-wrap"><pre class="language-json"><code>{
|
||
"version": "2.0.0",
|
||
"tasks": [
|
||
{
|
||
// Build firmware
|
||
"label": "Build Firmware",
|
||
"type": "shell",
|
||
"windows": {
|
||
"command": "cmd",
|
||
"args": [
|
||
"/c",
|
||
" cargo build && echo ✅ ◾ ️Done! "
|
||
]
|
||
},
|
||
"osx": {
|
||
"command": "bash",
|
||
"args": [
|
||
"-c", "-l",
|
||
" pkill openocd ; set -e -x ; cargo build ; echo ✅ ◾ ️Done! "
|
||
]
|
||
},
|
||
"linux": {
|
||
"command": "bash",
|
||
"args": [
|
||
"-c", "-l",
|
||
" pkill openocd ; set -e -x ; cargo build ; echo ✅ ◾ ️Done! "
|
||
]
|
||
},
|
||
"group": {
|
||
"kind": "build",
|
||
"isDefault": true
|
||
},
|
||
"problemMatcher": [
|
||
{
|
||
// Problem matcher for GNU Linker, e.g. /Users/Luppy/mynewt/stm32bluepill-mynewt-sensor/apps/my_sensor_app/src/ATParser.h:82: undefined reference to `operator delete[](void*)'
|
||
"fileLocation": [ "absolute" ],
|
||
"pattern": {
|
||
"regexp": "^(/.*):(\\d+):\\s+(.*)$",
|
||
"file": 1,
|
||
"line": 2,
|
||
"message": 3,
|
||
// "code": 3,
|
||
// "severity": 4,
|
||
}
|
||
}
|
||
],
|
||
"presentation": {
|
||
"clear": true
|
||
}
|
||
},
|
||
...</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> |