EmbeddedRelated.com
Blogs

VolksEEG: Rust Development On Adafruit nRF52840 Feather Express

Steve BranamDecember 13, 2021

Contents:


Introduction

In this post, I'll show you how to do Rust development on a new Adafruit Feather nRF52840 Express board, using the initial VolksEEG Project prototype application.

I used Ubuntu 20.04. However, because development takes place under VS Code running in a Docker container, you should be able to follow the same procedure on other development platforms with only minor platform-specific tweaks.

The application is based on a Rust RTIC (Real-Time Interrupt-driven Concurrency) demonstration app. Once the board has been flashed with the application, it runs as a serial echo-server. This is a nice way to prove out the development environment and device USB path, and have a playground for experimenting with Rust and RTIC.

This article is available in PDF format for easy printing

This builds on wiki pages and code in the VolksEEG repo contributed by other project participants:

A big thank you to them for providing all the source material so I could learn how to do this!

I don't know much about working with Docker, so that's another learning curve along with the other parts here. Given that this environment uses tools layered on top of tools, it can be challenging to diagnose and fix the problem when a failure occurs. I've included a container build failure and its fix as an example of how to address one such problem.


Setup

Hardware

Reference information:

Workstation

I'm running Ubuntu 20.04 x86_64 on a low-cost HP-14-dq0xxx laptop (Intel® Celeron(R) N4020 CPU @ 1.10GHz × 2, 4 GB RAM, 64 GB eMMC). This is a very low-end system, but has been sufficient so far.

sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ uname -a Linux sbranam-HP-Laptop-14-dq0xxx 5.11.0-41-generic #45~20.04.1-Ubuntu SMP Wed Nov 10 10:20:10 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Software Installed:

Workstation:

Board with USB and J-Link, powered up:

Closeup of board, powered down:

Software Checks

These verify basic board connection and operation.

USB Device

sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ lsusb ... Bus 001 Device 013: ID 239a:8029 Generic Flash Card Reader/Writer ... sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ ls -l /dev/ttyACM0 crw-rw---- 1 root dialout 166, 0 Dec 6 17:45 /dev/ttyACM0

Minicom

This connects to the board USB and shows the output of the pre-loaded flash image running on the board as it comes from Adafruit:

sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ sudo minicom -D /dev/ttyACM0 -b 115200 Welcome to minicom 2.7.1 OPTIONS: I18n Compiled on Dec 23 2019, 02:06:26. Port /dev/ttyACM0, 17:55:28 Press CTRL-A Z for help on special keys 02-01-06-19-16-F7-FD-01-0F-0E-59-2D-C0-2F-5D-68-92-DB-30-F0-BB-A1-C1-0B-00-00-00-00-03 Timestamp Addr Rssi Data 000580802 E7:A7:B7:95:89:22 -59 02-01-04-03-03-07-FE-10-FF-A7-05-05-10-01-00-00-00-00-00-00-02-1F-00-CA-03-19-00-00-02-0A-00 Timestamp Addr Rssi Data 000580815 7E:C8:6C:02:DTimestamp Addr Rssi Data 000609435 E7:A7:B7:95:89:22 -56 02-01-04-03-03-07-FE-10-FF-A7-05-05-10-01-00-00-00-00-00-00-02-1F-00-CA-03-19-00-00-02-0A-00 Timestamp Addr Rssi Data 000609520 E7:A7:B7:95:89:22 -62 02-01-04-03-03-07-FE-10-FF-A7-05-05-10-01-00-00-00-00-00-00-02-1F-00-CA-03-19-00-00-02-0A-00 Timestamp Addr Rssi Data 000609527 7E:C8:6C:02:DD:6E -71 02-01-06-13-FF-4C-00-0C-0E-00-78-23-74-B6-96-DB-77-0D-30-45-56-FC-A5 Timestamp Addr Rssi Data 000609610 E7:A7:B7:95:89:22 -56 02-01-04-03-03-07-FE-10-FF-A7-05-05-10-01-00-00-00-00-00-00-02-1F-00-CA-03-19-00-00-02-0A-00 Timestamp Addr Rssi Data 000609622 7E:C8:6C:02:DD:6E -67 02-01-06-13-FF-4C-00-0C-0E-00-78-23-74-B6-96-DB-77-0D-30-45-56-FC-A5 Timestamp Addr Rssi Data 000609718 7E:C8:6C:02:DD:6E -83 02-01-06-13-FF-4C-00-0C-0E-00-78-23-74-B6-96-DB-77-0D-30-45-56-FC-A5 Timestamp Addr Rssi Data 000609814 7E:C8:6C:02:DD:6E -71 02-01-06-13-FF-4C-00-0C-0E-00-78-23-74-B6-96-DB-77-0D-30-45-56-FC-A5 ... Timestamp Addr Rssi Data 000656634 7E:C8:6C:02:DD:6E -70 02-01-06-13-FF-4C-00-0C-0E-00-78-23-74-B6-96-DB-77-0D-30-45-56-FC-A5 Timestamp Addr Rssi Data 000656700 FA:0D:AC:42:4A:42 -68 02-01-06-19-16-F7-FD-01-0F-0E-59-2D-C0-2F-5D-68-92-DB-30-F0-BB-A1-C1-0B-00-00-00-00-03 CTRL-A Z for help | 115200 8N1 | NOR | Minicom 2.7.1 | VT102 | Offline | ttyACM0


JLinkExe

This connects over the J-Link debugger, via the SWD target interface:

sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ JLinkExe SEGGER J-Link Commander V7.58c (Compiled Nov 24 2021 17:24:52) DLL version V7.58c, compiled Nov 24 2021 17:24:36 Connecting to J-Link via USB...O.K. Firmware: J-Link EDU Mini V1 compiled Nov 2 2021 11:12:01 Hardware version: V1.00 S/N: 801035449 License(s): FlashBP, GDB VTref=3.272V Type "connect" to establish a target connection, '?' for help J-Link>connect Please specify device / core. : NRF52840_XXAA Type '?' for selection dialog Device> Please specify target interface: J) JTAG (Default) S) SWD T) cJTAG TIF>s Specify target interface speed [kHz]. : 4000 kHz Speed> Device "NRF52840_XXAA" selected. Connecting to target via SWD InitTarget() start InitTarget() end Found SW-DP with ID 0x2BA01477 DPIDR: 0x2BA01477 CoreSight SoC-400 or earlier Scanning AP map to find all available APs AP[2]: Stopped AP scan as end of AP map has been reached AP[0]: AHB-AP (IDR: 0x24770011) AP[1]: JTAG-AP (IDR: 0x02880000) Iterating through AP map to find AHB-AP to use AP[0]: Core found AP[0]: AHB-AP ROM base: 0xE00FF000 CPUID register: 0x410FC241. Implementer code: 0x41 (ARM) Found Cortex-M4 r0p1, Little endian. FPUnit: 6 code (BP) slots and 2 literal slots CoreSight components: ROMTbl[0] @ E00FF000 [0][0]: E000E000 CID B105E00D PID 000BB00C SCS-M7 [0][1]: E0001000 CID B105E00D PID 003BB002 DWT [0][2]: E0002000 CID B105E00D PID 002BB003 FPB [0][3]: E0000000 CID B105E00D PID 003BB001 ITM [0][4]: E0040000 CID B105900D PID 000BB9A1 TPIU [0][5]: E0041000 CID B105900D PID 000BB925 ETM Cortex-M4 identified. J-Link>halt PC = 00030886, CycleCnt = 0BCB3BD1 R0 = 00000001, R1 = 00000000, R2 = E000E100, R3 = 00000000 R4 = 20008C94, R5 = 00000000, R6 = 0000000A, R7 = 000064D4 R8 = 0000000A, R9 = 20007788, R10= 10000000, R11= E000ED00 R12= A5A5A5A5 SP(R13)= 20007C58, MSP= 2003FF98, PSP= 20007C58, R14(LR) = 00030849 XPSR = 61000000: APSR = nZCvq, EPSR = 01000000, IPSR = 000 (NoException) CFBP = 02000000, CONTROL = 02, FAULTMASK = 00, BASEPRI = 00, PRIMASK = 00 FPS0 = 00000000, FPS1 = 00000000, FPS2 = 00000000, FPS3 = 00000000 FPS4 = 00000000, FPS5 = 00000000, FPS6 = 00000000, FPS7 = 00000000 FPS8 = 00000000, FPS9 = 00000000, FPS10= 00000000, FPS11= 00000000 FPS12= 00000000, FPS13= 00000000, FPS14= 00000000, FPS15= 00000000 FPS16= 00000000, FPS17= 00000000, FPS18= 00000000, FPS19= 00000000 FPS20= 00000000, FPS21= 00000000, FPS22= 00000000, FPS23= 00000000 FPS24= 00000000, FPS25= 00000000, FPS26= 00000000, FPS27= 00000000 FPS28= 00000000, FPS29= 00000000, FPS30= 00000000, FPS31= 00000000 FPSCR= 01000000 J-Link>

The board does not support JTAG. Attempting to connect via JTAG causes the FTHR840BOOT device to auto-mount after several seconds; it automatically disconnects after 5 minutes. (The Adafruit Update Bootloader section says to double-click the reset button to get to this bootloader drive normally).

sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ JLinkExe SEGGER J-Link Commander V7.58c (Compiled Nov 24 2021 17:24:52) DLL version V7.58c, compiled Nov 24 2021 17:24:36 Connecting to J-Link via USB...O.K. Firmware: J-Link EDU Mini V1 compiled Nov 2 2021 11:12:01 Hardware version: V1.00 S/N: 801035449 License(s): FlashBP, GDB VTref=3.280V Type "connect" to establish a target connection, '?' for help J-Link>connect Please specify device / core. : NRF52840_XXAA Type '?' for selection dialog Device> Please specify target interface: J) JTAG (Default) S) SWD T) cJTAG TIF> Device position in JTAG chain (IRPre,DRPre) : -1,-1 => Auto-detect JTAGConf> Specify target interface speed [kHz]. : 4000 kHz Speed> Device "NRF52840_XXAA" selected. Connecting to target via JTAG InitTarget() start InitTarget() end Could not measure total IR len. TDO is constant high. InitTarget() start InitTarget() end Could not measure total IR len. TDO is constant high. InitTarget() start InitTarget() end Could not measure total IR len. TDO is constant high. InitTarget() start InitTarget() end Could not measure total IR len. TDO is constant high. Cannot connect to target. J-Link>q

FTHR840BOOT Contents

sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ cd /media/sbranam/FTHR840BOOT/ sbranam@sbranam-HP-Laptop-14-dq0xxx:/media/sbranam/FTHR840BOOT\$ ls -l total 151 -rw-r--r-- 1 sbranam sbranam 153088 Dec 31 1979 CURRENT.UF2 -rw-r--r-- 1 sbranam sbranam 108 Dec 31 1979 INDEX.HTM -rw-r--r-- 1 sbranam sbranam 212 Dec 31 1979 INFO_UF2.TXT sbranam@sbranam-HP-Laptop-14-dq0xxx:/media/sbranam/FTHR840BOOT\$ cat INDEX.HTM location.replace("https://www.adafruit.com/"); sbranam@sbranam-HP-Laptop-14-dq0xxx:/media/sbranam/FTHR840BOOT\$ cat INFO_UF2.TXT UF2 Bootloader 0.2.6 lib/nrfx (v1.1.0-1-g096e770) lib/tinyusb (legacy-525-ga1c59649) s140 6.1.1 Model: Adafruit Feather nRF52840 Express Board-ID: NRF52-Bluefruit-v0 Bootloader: s140 6.1.1 Date: Dec 21 2018

OpenOCD

Run in a separate terminal. A quick breakdown of the command:

  • The debug interface to the board is via J-Link (vs. for example, ST-Link).
  • The transport protocol is SWD (vs. for example, JTAG).
  • The target device is in the nRF52 series (vs. for example, STM32).
sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ openocd -f interface/jlink.cfg -c "transport select swd" -f target/nrf52.cfg Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html swd adapter speed: 10000 kHz cortex_m reset_config sysresetreq Info : No device selected, using first device. Info : J-Link EDU Mini V1 compiled Nov 2 2021 11:12:01 Info : Hardware version: 1.00 Info : VTarget = 3.274 V Info : Reduced speed from 10000 kHz to 4000 kHz (maximum). Info : Reduced speed from 10000 kHz to 4000 kHz (maximum). Info : clock speed 10000 kHz Info : SWD DPIDR 0x2ba01477 Info : nrf52.cpu: hardware has 6 breakpoints, 4 watchpoints

VolksEEG/eeg-device-firmware

Repo: VolksEEG/eeg-device-firmware (forked from VolksEEG)

PR "Merging initial implementation of the PC communications interface"

Pull Request #2

This version of the application is a simple serial echo-server: it opens a USB serial device and echoes any characters received. This is the intial prototype of the PC interface to stream EEG data to a USB-connected PC.

Container

Using VS Code, open this repo in a Dev Container (see Developing inside a Container). The container includes the Rust tools, including probe-rs, which allows debugging with a J-Link pod via OpenOCD over SWD. Everything is setup to run on a Nordic nRF52840_xxAA device.

The .devcontainer/ directory contains two files that configure the environment, providing VS Code extensions and Linux tools:

  • devcontainer.json configures VS Code to run in the container.
  • Dockerfile configures the container for Docker.

When you open the folder in a container for the first time, VS Code creates the container. This builds all the resources listed in the configuration.

Container Build Failure

Building the container initially fails. This serves as a useful example of what to do in this situation.

--- stderr thread 'main' panicked at 'Unable to find libudev: "pkg-config" "--libs" "--cflags" "libudev" did not exit successfully: exit status: 1 error: could not find system library 'libudev' required by the 'hidapi' crate --- stderr Package libudev was not found in the pkg-config search path. Perhaps you should add the directory containing 'libudev.pc' to the PKG_CONFIG_PATH environment variable No package 'libudev' found ', /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/hidapi-1.3.0/build.rs:55:54 note: run with 'RUST_BACKTRACE=1' environment variable to display a backtrace warning: build failed, waiting for other jobs to finish... [2021-12-11T20:03:15.623Z] error: failed to compile 'probe-run v0.3.1', intermediate artifacts can be found at '/tmp/cargo-install2Mf7Ei' Caused by: build failed Summary Successfully installed cargo-binutils! Failed to install probe-run (see error(s) above). [2021-12-11T20:03:15.624Z] error [2021-12-11T20:03:15.625Z] : some crates failed to install [3:47 PM] [2021-12-11T20:03:15.625Z] [2021-12-11T20:03:16.114Z] The command '/bin/sh -c cargo install cargo-binutils probe-run' returned a non-zero code: 101 [2021-12-11T20:03:16.126Z] Stop (460061 ms): Run: docker build -f /home/sbranam/repos/eeg-device-firmware/.devcontainer/Dockerfile -t vsc-eeg-device-firmware-09213f71b2a9a6a22eec247ac1b0d25b --build-arg VARIANT=bullseye /home/sbranam/repos/eeg-device-firmware/.devcontainer [2021-12-11T20:03:16.135Z] Command failed: docker build -f /home/sbranam/repos/eeg-device-firmware/.devcontainer/Dockerfile -t vsc-eeg-device-firmware-09213f71b2a9a6a22eec247ac1b0d25b --build-arg VARIANT=bullseye /home/sbranam/repos/eeg-device-firmware/.devcontainer

This is because the hidapi crate requires the libudev library, which is not provided by default.

Container Build Fix

Fix the build by adding libudev-dev to the Dockerfile apt-get install command:

diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 31c86c4..2ad34a2 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -5,7 +5,7 @@ ARG VARIANT="bullseye" FROM mcr.microsoft.com/vscode/devcontainers/rust:0-\${VARIANT} RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends build-essential gdb-multiarch libusb-1.0 openocd + && apt-get -y install --no-install-recommends build-essential gdb-multiarch libusb-1.0 openocd libudev-dev RUN rustup component add clippy llvm-tools-preview rustfmt RUN cargo install cargo-binutils probe-run

This results in a successful open of the container.

Opened Container

All subsequent operations take place in VS Code in the container.

sbranam@sbranam-HP-Laptop-14-dq0xxx:~/repos/eeg-device-firmware\$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7e4b45d20e7a vsc-eeg-device-firmware-09213f71b2a9a6a22eec247ac1b0d25b-uid "/bin/sh -c 'echo Co…" 6 hours ago Up 6 hours priceless_kare

Debugging

The VS Code debugger interface runs probe-rs, which runs OpenOCD (with gdb-server) and gdb.

File openocd.cfg selects the J-Link interface with SWD transport, for an nRF52 target.

This opens the VS Code debugger GUI (see Visual Studio Code: Debugging), including the source code pane, with the following outputs:

  • DEBUG CONSOLE: gdb terminal interface.
  • TERMINAL Cargo Build (debug): Rust build output.
  • TERMINAL gdb-server: OpenOCD output.

You can use the VS Code debugger source pane to set breakpoints. You can use the debugger GUI toolbar to run the code or step through it.

Processes:

sbranam@sbranam-HP-Laptop-14-dq0xxx:~/repos/eeg-device-firmware\$ ps aux | grep -e docker -e openocd -e gdb root 1253 0.0 0.9 1020892 35072 ? Ssl Dec08 0:43 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock sbranam 171005 0.0 1.4 683708 55664 ? Sl 21:46 0:00 docker exec -i -u vscode -e VSCODE_REMOTE_CONTAINERS_SESSION=f92717a4-1aab-498c-bead-8930d3e563bd1639277215491 7e4b45d20e7a80191ae6d9b78eabbeff2dc663a29f02824290efe06d93feda7f /bin/sh sbranam 171046 0.0 1.4 683708 56088 ? Sl 21:46 0:00 docker exec -i -u root 7e4b45d20e7a80191ae6d9b78eabbeff2dc663a29f02824290efe06d93feda7f /bin/sh sbranam 171084 0.0 1.4 683708 56428 ? Sl 21:46 0:00 docker exec -i -u vscode -e REMOTE_CONTAINERS_SOCKETS=["/tmp/vscode-ssh-auth-6f5f681c196403fc48cb5bec39b949b35f73cc86.sock","/home/vscode/.gnupg/S.gpg-agent"] -e REMOTE_CONTAINERS_IPC=/tmp/vscode-remote-containers-ipc-6f5f681c196403fc48cb5bec39b949b35f73cc86.sock 7e4b45d20e7a80191ae6d9b78eabbeff2dc663a29f02824290efe06d93feda7f /home/vscode/.vscode-server/bin/3a6960b964327f0e3882ce18fcebd07ed191b316/node /tmp/vscode-remote-containers-server-6f5f681c196403fc48cb5bec39b949b35f73cc86.js sbranam 171216 0.1 1.5 757440 57572 ? Sl 21:46 0:00 docker exec -i -u vscode -e VSCODE_REMOTE_CONTAINERS_SESSION=f92717a4-1aab-498c-bead-8930d3e563bd1639277215491 7e4b45d20e7a80191ae6d9b78eabbeff2dc663a29f02824290efe06d93feda7f /home/vscode/.vscode-server/bin/3a6960b964327f0e3882ce18fcebd07ed191b316/node -e ????const net = require('net'); ????process.stdin.pause(); ????const client = net.createConnection({ port: 46117 }, () => { ?????client.pipe(process.stdout); ?????process.stdin.pipe(client); ????}); ????client.on('close', function (hadError) { ?????console.error(hadError ? 'Remote close with error' : 'Remote close'); ?????process.exit(hadError ? 1 : 0); ????}); ????client.on('error', function (err) { ?????process.stderr.write(err && (err.stack || err.message) || String(err)); ????}); ??? sbranam 171311 0.1 1.4 757440 56436 ? Sl 21:47 0:00 docker exec -i -u vscode -e VSCODE_REMOTE_CONTAINERS_SESSION=f92717a4-1aab-498c-bead-8930d3e563bd1639277215491 7e4b45d20e7a80191ae6d9b78eabbeff2dc663a29f02824290efe06d93feda7f /home/vscode/.vscode-server/bin/3a6960b964327f0e3882ce18fcebd07ed191b316/node -e ????const net = require('net'); ????process.stdin.pause(); ????const client = net.createConnection({ port: 46117 }, () => { ?????client.pipe(process.stdout); ?????process.stdin.pipe(client); ????}); ????client.on('close', function (hadError) { ?????console.error(hadError ? 'Remote close with error' : 'Remote close'); ?????process.exit(hadError ? 1 : 0); ????}); ????client.on('error', function (err) { ?????process.stderr.write(err && (err.stack || err.message) || String(err)); ????}); ??? sbranam 171581 1.0 0.2 25856 9120 ? Sl 21:47 0:01 openocd -c gdb_port 50000 -c tcl_port 50001 -c telnet_port 50002 -s /workspaces/eeg-device-firmware -f ./openocd.cfg -c tpiu config internal :50003 uart off 8000000 2000000 sbranam 171584 0.2 1.1 242092 43768 ? Sl 21:47 0:00 /usr/bin/gdb-multiarch -q --interpreter=mi2 /workspaces/eeg-device-firmware/target/thumbv7em-none-eabihf/debug/volks-fw

TERMINAL gdb-server Output

[2021-12-11T22:01:07.831Z] SERVER CONSOLE DEBUG: onBackendConnect: gdb-server session connected. You can switch to "DEBUG CONSOLE" to see GDB interactions. Open On-Chip Debugger 0.11.0-rc2 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : Listening on port 50003 for armv7m_trace connections Info : Listening on port 50001 for tcl connections Info : Listening on port 50002 for telnet connections Info : J-Link EDU Mini V1 compiled Nov 2 2021 11:12:01 Info : Hardware version: 1.00 Info : VTarget = 3.290 V Info : clock speed 1000 kHz Info : SWD DPIDR 0x2ba01477 Info : nrf52.cpu: hardware has 6 breakpoints, 4 watchpoints Info : starting gdb server for nrf52.cpu on 50000 Info : Listening on port 50000 for gdb connections Info : accepting 'armv7m_trace' connection on tcp/50003 Info : accepting 'gdb' connection on tcp/50000 Info : nRF52840-xxAA(build code: D0) 1024kB Flash, 256kB RAM undefined debug reason 8 - target needs reset target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000

DEBUG CONSOLE Output

Please check TERMINAL tab (gdb-server) for output from openocd Launching server: "openocd" "-c" "gdb_port 50000" "-c" "tcl_port 50001" "-c" "telnet_port 50002" "-s" "/workspaces/eeg-device-firmware" "-f" "./openocd.cfg" "-c" "tpiu config internal :50003 uart off 8000000 2000000" Launching GDB: "/usr/bin/gdb-multiarch" "-q" "--interpreter=mi2" "/workspaces/eeg-device-firmware/target/thumbv7em-none-eabihf/debug/volks-fw"Set "showDevDebugOutput": true in your "launch.json" to see verbose GDB transactions here. Helpful to debug issues or report problems Reading symbols from /workspaces/eeg-device-firmware/target/thumbv7em-none-eabihf/debug/volks-fw... 0x0000fe70 in core::ptr::const_ptr::{impl#0}::guaranteed_eq (self=0xff1b ::new+26>, other=0x0 ) at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/const_ptr.rs:423 423 /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/const_ptr.rs: No such file or directory. Program stopped, probably due to a reset and/or halt issued by debugger target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 Warning: the current language does not match this frame. Note: automatically using hardware breakpoints for read-only addresses. Temporary breakpoint 1, volks_fw::app::rtic_ext::main () at volks-fw/src/main.rs:8 8 #[rtic::app(device = hal::pac, peripherals = true, dispatchers = [SWI0_EGU0])]

Running Application

In the source code, file volks-fw/src/main.rs defines a USB device builder:

let usb_dev = UsbDeviceBuilder::new(usb_bus, UsbVidPid(0x16c0, 0x27dd)) .manufacturer("Volks EEG") .product("Serial port") .serial_number("TEST") .device_class(USB_CLASS_CDC) .max_packet_size_0(64) // (makes control transfers 8x faster) .build();

Device Hunt lists this USB Vendor ID/Product ID pair as:

Type Vendor ID Vendor Name Device ID Device Name
USB 16C0 Van Ooijen Technical Informatics 27DD CDC-ACM class devices (modems)

When the application runs, the device identifies itself as this:

sbranam@sbranam-HP-Laptop-14-dq0xxx:~/repos/eeg-device-firmware\$ lsusb ... Bus 001 Device 048: ID 16c0:27dd Van Ooijen Technische Informatica CDC-ACM class devices (modems) ...

Running minicom on the device results in echoing any input:

sbranam@sbranam-HP-Laptop-14-dq0xxx:~\$ sudo minicom -D /dev/ttyACM0 -b 115200 Welcome to minicom 2.7.1 OPTIONS: I18n Compiled on Dec 23 2019, 02:06:26. Port /dev/ttyACM0, 14:43:35 Press CTRL-A Z for help on special keys This is the echo!!!! CTRL-A Z for help | 115200 8N1 | NOR | Minicom 2.7.1 | VT102 | Offline | ttyACM0

Test Modifications

I made the following modifications to add my username to the program output to prove signs of life end-to-end through the toolchain (see Dumb Embedded System Mistakes: Running The Wrong Code for why I do this).

Serial Output

This change adds the username to the serial echo output:

diff --git a/pc-communications-hal/src/pc_coms_hal.rs b/pc-communications-hal/src/pc_coms_hal.rs index 82e5733..a24dc0c 100644 --- a/pc-communications-hal/src/pc_coms_hal.rs +++ b/pc-communications-hal/src/pc_coms_hal.rs @@ -250,6 +250,9 @@ impl PcInterfaceTrait for PcInterface { /// add the passed data to the transmit buffer, to be sent out /// as part of the background task fn set_data_to_transmit(&mut self, data: [u8; 64], count: u8) { + for s in "\n\rsbranam echo: ".bytes() { + self.add_byte_to_tx_buffer(s); + } // push all the data to the tx buffer for b in data[0..count as usize].iter() { self.add_byte_to_tx_buffer(*b);

Minicom output:

sbranam echo: a sbranam echo: b sbranam echo: c sbranam echo: d sbranam echo: e sbranam echo: f CTRL-A Z for help | 115200 8N1 | NOR | Minicom 2.7.1 | VT102 | Offline | ttyACM0

Semihosting Output

Semihosting sends output over the debugger connection to the host debug serial output, in this case over the J-Link to the OpenOCD terminal, via the hprintln! macro (see Semihosting - The Embedded Rust Book). This allows you to print debug messages without using the board's USB connection.

Changes:

diff --git a/volks-fw/Cargo.toml b/volks-fw/Cargo.toml index dab3ec5..bc86d41 100644 --- a/volks-fw/Cargo.toml +++ b/volks-fw/Cargo.toml @@ -30,3 +30,4 @@ systick-monotonic = "0.1.0-rc.2" nrf52840-pac = "0.10.1" usb-device = "0.2.7" usbd-serial = "0.1.0" +cortex-m-semihosting = "0.3.3" diff --git a/volks-fw/src/main.rs b/volks-fw/src/main.rs index 17a9731..d1d6674 100644 --- a/volks-fw/src/main.rs +++ b/volks-fw/src/main.rs @@ -88,6 +88,7 @@ mod app { #[idle(local = [pc_interface])] fn idle(mut _ctx: idle::Context) -> ! { + use cortex_m_semihosting::hprintln; // local copy of the pc interface let pc = _ctx.local.pc_interface; @@ -99,6 +100,7 @@ mod app { // if there is data then transmit if back out if rx.bytes_available > 0 { + hprintln!("sbranam echo: {}", rx.data_array[0] as char).unwrap(); pc.set_data_to_transmit(rx.data_array, rx.bytes_available); } }

To see the output, you first need to enable semihosting in OpenOCD, with the mon arm semihosting enable command in the DEBUG CONSOLE:

> mon arm semihosting enable semihosting is enabled

If you forget to enable semihosting, the debugger will break at __c_m_sh_syscall@0x00003cee (Unknown Source:0). You can enable semihosting at that point and continue.

TERMINAL gdb-server output:

[2021-12-11T22:01:07.831Z] SERVER CONSOLE DEBUG: onBackendConnect: gdb-server session connected. You can switch to "DEBUG CONSOLE" to see GDB interactions. Open On-Chip Debugger 0.11.0-rc2 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : Listening on port 50003 for armv7m_trace connections Info : Listening on port 50001 for tcl connections Info : Listening on port 50002 for telnet connections Info : J-Link EDU Mini V1 compiled Nov 2 2021 11:12:01 Info : Hardware version: 1.00 Info : VTarget = 3.290 V Info : clock speed 1000 kHz Info : SWD DPIDR 0x2ba01477 Info : nrf52.cpu: hardware has 6 breakpoints, 4 watchpoints Info : starting gdb server for nrf52.cpu on 50000 Info : Listening on port 50000 for gdb connections Info : accepting 'armv7m_trace' connection on tcp/50003 Info : accepting 'gdb' connection on tcp/50000 Info : nRF52840-xxAA(build code: D0) 1024kB Flash, 256kB RAM undefined debug reason 8 - target needs reset target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000100 msp: 0x20040000 semihosting is enabled sbranam echo: a sbranam echo: b sbranam echo: c sbranam echo: d


To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.

Please login (on the right) if you already have an account on this platform.

Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: