[Embedded Rust] How can one debug STM32/OpenOCD from CLion/IntelliJ Rust?


#1

I’m trying to debug an ARM binary running on a STM32F3DISCOVERY board using CLion + IntelliJ Rust.

I’ve been following @japaric’s excellent discovery blog, where he describes how to debug an STM32 binary using gdb from the command line through openocd, and that works great:

For increased productivity, I’d like to debug natively within the CLion IDE.

The openocd command used is:

$ openocd \
  -f interface/stlink-v2-1.cfg \
  -f target/stm32f3x.cfg

Which opens a GDB server on port 3333.

The sample program I am trying to load is from an LED routlette example:

#![deny(unsafe_code)]
#![no_main]
#![no_std]

extern crate aux5;
#[macro_use]
extern crate cortex_m_rt;

use aux5::prelude::*;
use aux5::{Delay, Leds};

entry!(main);

fn main() -> ! {
    let (mut delay, mut leds): (Delay, Leds) = aux5::init();

    let ms = 50_u8;
    loop {
        for curr in 0..8 {
            let next = (curr + 1) % 8;

            leds[next].on();
            delay.delay_ms(ms);
            leds[curr].off();
            delay.delay_ms(ms);
        }
    }
}

CLion supports a Remote Debug run configuration, which I’ve so far configured like (testing in CLion 2018.1.6 on macOS):

If a binary has already been loaded through gdb from the command line, CLion is able to connect and run the binary remotely, and pausing will pause the microcontroller and show disassembly in the CLion window.

The following things don’t work at the moment:

  • Loading a compiled binary from CLion
  • Viewing / stepping through the Rust source
  • Inputting breakpoints from the IDE

Does anyone have any ideas on how to improve this?

It looks like one user, @perlindgren has attempted this as well:

I’m experimenting with debugging Rust on embedded (Nucleo STM32F401re) using openocd and arm-none-eabi-gdb. I have it somewhat working. Here is the current status.

  1. The program is not loaded. (I had to use the pause and in the gdb console load it, the file has the right path, so it loads correctly)
  2. Breakpoints do not work, setting them in the IDE has no effect, stepping works and even (surprisingly) run to line. Setting breakpoints in the gdb console works fine.
  3. Variables are sometimes not shown. When they work, they are also updated in the source file. However mouse overs never work.
  4. Watching local (stack) as well as static (heap) variables always work.

I’m on the latest nightly xargo/cargo and nightly rustup channel. Arch linux with the CLion December 26 build. The bebug config:
/usr/bin/arm-none-eabi-gdb
(GNU gdb (GDB) 8.0.1)
‘target remote’ args: :3333
Symbol file:/home/pln/CLionProjects/rtfm-app/target/thumbv7em-none-eabihf/debug/examples/bare0
Sysroot:
(Empty)

To me it seems not so far from working and the Rust support in CLion looks promising (perhaps the best amongst RustDT (not supported), and vscode (RLS based)). So a couple of questions/remarks.
.gbinit will run before the ‘target remote’ from the plugin is launched. I tried to use that to load the binary, but I did not get that to work. It would be better with a ‘classic’ script option, allowing you to override the default connection procedure. Regarding the breakpoint integration, I have no clue what is wrong, as there seems to be some connection in between the IDE and gdb. (Rust uses C++ style namespaces/symbols, so that should not be a problem.) Another observation, if you try run to line, on a line not reachable, the debugger will not halt even if you press pause. I also tried using the OpenOCD Dowload & Run plugin, but it did not do the trick as being tailored to C/C++ (It could be a good stard for a dedicated Rust embedded debug plugin though…).

CC @matklad @Undin