lupyuen.org/articles/debug.html

800 lines
No EOL
47 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<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="Whats Next">8 Whats 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 well 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&amp;GDB/en">Note: Theres 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 &quot;$PWD/xpack-riscv-none-embed-gcc/bin/riscv-none-embed-gdb&quot; &quot;$PWD/xpack-riscv-none-embed-gcc/bin/riscv64-unknown-elf-gdb&quot;</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>Lets 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… Well cover them in a while.</p>
<div class="example-wrap"><pre class="language-text"><code>warning: unused imports: `clock::Strict`, `serial::*`
--&gt; 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`
--&gt; 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
--&gt; 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 BL602s 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 youre interested only in VSCode debugging, skip to the next section)</p>
<p>Lets run the Rust Firmware and debug it with GDB. Well 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 (&lt;unknown&gt;), 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 (&lt;unknown&gt;), 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=&quot;$PWD/xpack-riscv-none-embed-gcc/bin:$PATH&quot;
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 PineCones 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. (Well 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>Well 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 were 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 well see this warning… Just ignore it</p>
<div class="example-wrap"><pre class="language-text"><code>Info : accepting &#39;gdb&#39; 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>Whats driving GDB? How does GDB know how to do the things that it did?</em></p>
<p>Thats the purpose of the GDB Script. Lets look inside <a href="https://github.com/lupyuen/pinecone-rust/blob/main/openocd.gdb"><code>openocd.gdb</code></a></p>
<ol>
<li>
<p>GDB doesnt 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>Heres 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 dont 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 BL602s 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 = [
&quot;-C&quot;, &quot;link-arg=-Tmemory.x&quot;,
&quot;-C&quot;, &quot;link-arg=-Tlink.x&quot;,
]
runner = &quot;riscv64-unknown-elf-gdb -q -x openocd.gdb&quot;
## runner = &quot;riscv32-unknown-elf-gdb -q -x openocd.gdb&quot;
[build]
target = &quot;riscv32imac-unknown-none-elf&quot;</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, lets 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() -&gt; ! {
<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… Lets 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() -&gt; ! {</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>-&gt; !</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>Heres 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>BL602s 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 well 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>Wheres the rest of the Rust code?</em></p>
<p>This program was originally created for Sipeeds BL602 Board… But some parts dont work on PineCone and have been commented out. (Hence the compiler warnings)</p>
<p>Well 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 PineCones 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 were 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>Thats 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 dont work on PineCone. (Because the code was created for Sipeeds BL602 Board)</p>
<p>Lets 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">&amp;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 wont 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 PineCones 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 PineCones 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 Whats Next</h1>
<p>Now that we have GDB and VSCode Debuggers working with Rust Firmware on PineCone… Its 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
&quot;version&quot;: &quot;0.2.0&quot;,
&quot;configurations&quot;: [
{
&quot;name&quot;: &quot;BL602&quot;,
&quot;type&quot;: &quot;gdb&quot;,
&quot;request&quot;: &quot;launch&quot;,
// Application Executable to be flashed before debugging
&quot;target&quot;: &quot;${workspaceRoot}/target/riscv32imac-unknown-none-elf/debug/bl602-rust-guide&quot;,
&quot;cwd&quot;: &quot;${workspaceRoot}&quot;,
&quot;gdbpath&quot;: &quot;${workspaceRoot}/xpack-riscv-none-embed-gcc/bin/riscv-none-embed-gdb&quot;,
&quot;valuesFormatting&quot;: &quot;parseText&quot;,
&quot;autorun&quot;: [
// Before loading the Application, run these gdb commands.
// Set timeout for executing openocd commands.
&quot;set remotetimeout 600&quot;,
// This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
&quot;set breakpoint pending on&quot;,
// Set breakpoints
&quot;break main&quot;, // Break at main()
// Launch OpenOCD. Based on https://www.justinmklam.com/posts/2017/10/vscode-debugger-setup/
&quot;target remote | xpack-openocd/bin/openocd -c \&quot;gdb_port pipe; log_output openocd.log\&quot; -f openocd.cfg &quot;,
// Load the program into cache memory
&quot;load&quot;,
// Run the program until we hit the main() breakpoint
&quot;continue&quot;,
]
}
]
}</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>{
&quot;version&quot;: &quot;2.0.0&quot;,
&quot;tasks&quot;: [
{
// Build firmware
&quot;label&quot;: &quot;Build Firmware&quot;,
&quot;type&quot;: &quot;shell&quot;,
&quot;windows&quot;: {
&quot;command&quot;: &quot;cmd&quot;,
&quot;args&quot;: [
&quot;/c&quot;,
&quot; cargo build &amp;&amp; echo ✅ ◾ Done! &quot;
]
},
&quot;osx&quot;: {
&quot;command&quot;: &quot;bash&quot;,
&quot;args&quot;: [
&quot;-c&quot;, &quot;-l&quot;,
&quot; pkill openocd ; set -e -x ; cargo build ; echo ✅ ◾ Done! &quot;
]
},
&quot;linux&quot;: {
&quot;command&quot;: &quot;bash&quot;,
&quot;args&quot;: [
&quot;-c&quot;, &quot;-l&quot;,
&quot; pkill openocd ; set -e -x ; cargo build ; echo ✅ ◾ Done! &quot;
]
},
&quot;group&quot;: {
&quot;kind&quot;: &quot;build&quot;,
&quot;isDefault&quot;: true
},
&quot;problemMatcher&quot;: [
{
// 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*)&#39;
&quot;fileLocation&quot;: [ &quot;absolute&quot; ],
&quot;pattern&quot;: {
&quot;regexp&quot;: &quot;^(/.*):(\\d+):\\s+(.*)$&quot;,
&quot;file&quot;: 1,
&quot;line&quot;: 2,
&quot;message&quot;: 3,
// &quot;code&quot;: 3,
// &quot;severity&quot;: 4,
}
}
],
&quot;presentation&quot;: {
&quot;clear&quot;: 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>