Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channel<ThreadModeRawMutex, can::frame::FdFrame, 64> causes probe disconnect #3769

Open
justinberi opened this issue Jan 14, 2025 · 1 comment

Comments

@justinberi
Copy link

justinberi commented Jan 14, 2025

Preamble

I am fairly new to Rust embedded and completely new to embassy so please let me know if this is not the right place for this issue. I'm also happy to try out anything you suggest may work. Thanks in advance for your help.

Description

Using can::frame::FdFrame as the inner type causes my debug probe to disconnect after flashing. Using probe-rs attach after the disconnect shows that the firmware was successfully flashed and is running but the probe was disconnected when running cargo run --bin test_can --release.

With reference to the minimal example below. Setting type ChannelInner = TestWorking;

$ cargo run --bin test_can --release
   Compiling demo v0.1.0 (/home/justin/Documents/project_x/demo/demo_node)
    Finished `release` profile [optimized + debuginfo] target(s) in 0.20s
     Running `probe-rs run --chip STM32G474RE --connect-under-reset target/thumbv7em-none-eabi/release/test_can`
      Erasing ✔ 100% [####################]  20.00 KiB @  64.60 KiB/s (took 0s)
  Programming ✔ 100% [####################]  19.00 KiB @  27.36 KiB/s (took 1s)                                                                                                              Finished in 0.69s
0.000000 TRACE BDCR ok: 00008200
└─ embassy_stm32::rcc::bd::{impl#3}::init @ /home/justin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-stm32-0.2.0/src/rcc/bd.rs:216 
0.000000 DEBUG rcc: Clocks { hclk1: MaybeHertz(16000000), hclk2: MaybeHertz(16000000), hclk3: MaybeHertz(16000000), hse: MaybeHertz(0), hsi48: MaybeHertz(48000000), pclk1: MaybeHertz(16000000), pclk1_tim: MaybeHertz(16000000), pclk2: MaybeHertz(16000000), pclk2_tim: MaybeHertz(16000000), pll1_p: MaybeHertz(0), pll1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(16000000) }
└─ embassy_stm32::rcc::set_freqs @ /home/justin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-stm32-0.2.0/src/rcc/mod.rs:71  
0.000030 INFO  Boop
└─ test_can::__serial_heartbeat_task::{async_fn#0} @ src/bin/test_can.rs:36  
1.000122 INFO  Boop
└─ test_can::__serial_heartbeat_task::{async_fn#0} @ src/bin/test_can.rs:36  
2.000244 INFO  Boop
└─ test_can::__serial_heartbeat_task::{async_fn#0} @ src/bin/test_can.rs:36

Setting type ChannelInner = TestNotWorking; causes the following behaviour

$ cargo run --bin test_can --release
    Finished `release` profile [optimized + debuginfo] target(s) in 0.06s
     Running `probe-rs run --chip STM32G474RE --connect-under-reset target/thumbv7em-none-eabi/release/test_can`
      Erasing ✔ 100% [####################]  20.00 KiB @  64.76 KiB/s (took 0s)
  Programming ✔ 100% [####################]  20.00 KiB @  28.12 KiB/s (took 1s)                                                                                                              Finished in 0.71s
 WARN probe_rs::probe::stlink: send_jtag_command 242 failed: SwdApFault
Error: Error communicating with the probe.

Caused by:
    0: An ARM specific error occurred.
    1: The debug probe encountered an error.
    2: An error which is specific to the debug probe in use occurred.
    3: Command failed with status SwdApFault.

then after resetting the board and running probe-rs attach

$ probe-rs attach --chip STM32G474RE target/thumbv7em-none-eabi/release/test_can
0.000000 TRACE BDCR ok: 00008200
└─ embassy_stm32::rcc::bd::{impl#3}::init @ /home/justin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-stm32-0.2.0/src/rcc/bd.rs:216 
0.000000 DEBUG rcc: Clocks { hclk1: MaybeHertz(16000000), hclk2: MaybeHertz(16000000), hclk3: MaybeHertz(16000000), hse: MaybeHertz(0), hsi48: MaybeHertz(48000000), pclk1: MaybeHertz(16000000), pclk1_tim: MaybeHertz(16000000), pclk2: MaybeHertz(16000000), pclk2_tim: MaybeHertz(16000000), pll1_p: MaybeHertz(0), pll1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(16000000) }
└─ embassy_stm32::rcc::set_freqs @ /home/justin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-stm32-0.2.0/src/rcc/mod.rs:71  
0.000091 INFO  Boop
└─ test_can::__serial_heartbeat_task::{async_fn#0} @ src/bin/test_can.rs:36  
1.000183 INFO  Boop
└─ test_can::__serial_heartbeat_task::{async_fn#0} @ src/bin/test_can.rs:36  
2.000305 INFO  Boop
└─ test_can::__serial_heartbeat_task::{async_fn#0} @ src/bin/test_can.rs:36  

As a work around, the probe remains connected if I

  1. physically disconnect the probe from the board
  2. hold the reset down and connect the probe
  3. do cargo run --bin test_can --release whilst still holding reset down
$ cargo run --bin test_can --release
    Finished `release` profile [optimized + debuginfo] target(s) in 0.04s
     Running `probe-rs run --chip STM32G474RE --connect-under-reset target/thumbv7em-none-eabi/release/test_can`
 WARN probe_rs::session: Could not clear all hardware breakpoints: An ARM specific error occurred.

Caused by:
    A timeout occurred during an operation.
Error: Connecting to the chip was unsuccessful.

Caused by:
    Timeout while attaching to target under reset. This can happen if the target is not responding to the reset sequence. Ensure the chip's reset pin is connected, or try attaching without reset (`connectUnderReset = false` for DAP Clients, or remove `connect-under-reset` option from CLI options.).
  1. release reset button and flash again with cargo run --bin test_can --release
$ cargo run --bin test_can --release
    Finished `release` profile [optimized + debuginfo] target(s) in 0.04s
     Running `probe-rs run --chip STM32G474RE --connect-under-reset target/thumbv7em-none-eabi/release/test_can`
      Erasing ✔ 100% [####################]  20.00 KiB @  64.47 KiB/s (took 0s)
  Programming ✔ 100% [####################]  20.00 KiB @  28.08 KiB/s (took 1s)                                                                                                              Finished in 0.71s
0.000000 TRACE BDCR configured: 00008200
└─ embassy_stm32::rcc::bd::{impl#3}::init::{closure#4} @ /home/justin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-stm32-0.2.0/src/rcc/bd.rs:280 
0.000000 DEBUG rcc: Clocks { hclk1: MaybeHertz(16000000), hclk2: MaybeHertz(16000000), hclk3: MaybeHertz(16000000), hse: MaybeHertz(0), hsi48: MaybeHertz(48000000), pclk1: MaybeHertz(16000000), pclk1_tim: MaybeHertz(16000000), pclk2: MaybeHertz(16000000), pclk2_tim: MaybeHertz(16000000), pll1_p: MaybeHertz(0), pll1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(16000000) }
└─ embassy_stm32::rcc::set_freqs @ /home/justin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-stm32-0.2.0/src/rcc/mod.rs:71  
0.000091 INFO  Boop
└─ test_can::__serial_heartbeat_task::{async_fn#0} @ src/bin/test_can.rs:36  

Expected Behaviour

The probe should remain connected with type ChannelInner = TestNotWorking; when cargo run --bin test_can --release is run.

Minimal Example

src/bin/test_can.rs

#![no_std]
#![no_main]
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::Config;
use embassy_stm32::can;
use embassy_time::Timer;
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_sync::channel::Channel;
use {defmt_rtt as _, panic_probe as _};

// Define some types to make it easier to test the error
type TestNotWorking = can::frame::FdFrame; // This doesn't work
type TestWorking = &'static [u8]; // This does work


type ChannelInner = TestNotWorking; // Change this line to trial the working vs non-working types
type CanChannel = Channel<ThreadModeRawMutex, ChannelInner, 64>;
static CHANNEL: CanChannel = Channel::new();

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let _peripherals = embassy_stm32::init(Config::default());
    unwrap!(_spawner.spawn(serial_heartbeat()) ); // just for info

    // ERROR: This line causes probe disconnect when using can::frame::FdFrame (TestNotWorking) type
    CHANNEL.send(ChannelInner::make_it()).await;
    //

}

/// Spam the serial line 
#[embassy_executor::task]
async fn serial_heartbeat() {
    loop {
        info!("Boop");
        Timer::after_millis(1000).await;
    }
}

// "Constructor" trait
trait MakeIt {
    fn make_it() -> Self;
}

impl MakeIt for TestNotWorking {
    fn make_it() -> Self {
        can::frame::FdFrame::new_standard(0, &[0 as u8; 8]).unwrap()
    }
}

impl MakeIt for TestWorking {
    fn make_it() -> Self {
        static TEST_DATA: [u8; 8] = [0,1,2,3,4,5,6,7];
        &TEST_DATA
    }
}

.cargo/config.toml

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# replace STM32G071C8Rx with your chip as listed in `probe-rs chip list`
runner = "probe-rs run --chip STM32G474RE --connect-under-reset"

[build]
target = "thumbv7em-none-eabi"

[env]
DEFMT_LOG = "trace"

Cargo.toml

[package]
name = "demo"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
embassy-executor = {version="0.7.0", features = ["arch-cortex-m", "executor-thread", "defmt"] }
embassy-futures = "0.1.1"
embassy-stm32 = { version = "0.2.0", features = [
    "defmt",
    "time-driver-any",
    "stm32g474re",
    "memory-x",
    "unstable-pac",
    "exti",
] }
embassy-sync = { version = "0.6.1", features = ["defmt"]}
embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"]}

defmt = "0.3.10"
defmt-rtt = "0.4.1"

cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "1.0.0"
embedded-can = { version = "0.4" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
static_cell = "2.0.0"

heapless = "0.7.0"
postcard = {version="1.1.1"}

[profile.release]
debug = 2

build.rs

fn main() {
    println!("cargo:rustc-link-arg-bins=--nmagic");
    println!("cargo:rustc-link-arg-bins=-Tlink.x");
    println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}

Environment

host: Ubuntu 24.04

target: NUCLEO-G474RE

$ probe-rs list
The following debug probes were found:
[0]: STLink V3 -- 0483:374e:0053003E3133510337363734 (ST-LINK)
@justinberi
Copy link
Author

It appears to be related to the use of the "defmt" feature within the can module of the embassy-stm32 crate. Commenting the feature out in Cargo.toml

embassy-stm32 = { version = "0.2.0", features = [
   # "defmt",
    "time-driver-any",
    "stm32g474re",
    "memory-x",
    "unstable-pac",
    "exti",
] }

and removing defmt macros in test_can.rs result in the probe remaining connected.

$ cargo run --bin test_can --release
   Compiling demo v0.1.0 (/home/justin/Documents/project_x/demo/demo_node)
warning: unused import: `defmt::*`
 --> src/bin/test_can.rs:3:5
  |
3 | use defmt::*;
  |     ^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: `demo` (bin "test_can") generated 1 warning (run `cargo fix --bin "test_can"` to apply 1 suggestion)
    Finished `release` profile [optimized + debuginfo] target(s) in 0.21s
     Running `probe-rs run --chip STM32G474RE --connect-under-reset target/thumbv7em-none-eabi/release/test_can`
      Erasing ✔ 100% [####################]  22.00 KiB @  65.00 KiB/s (took 0s)
  Programming ✔ 100% [####################]  22.00 KiB @  28.18 KiB/s (took 1s)                                                                                                              Finished in 0.78s

adding back the defmt macros only, disconnects the probe again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant