From f72935b25cd348e278f9af9b53bff66cbcae1f50 Mon Sep 17 00:00:00 2001 From: Jon Lamb Date: Thu, 28 Mar 2024 18:02:37 -0700 Subject: [PATCH] Update RTT collector --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/bin/rtt_collector.rs | 69 ++++++++++++++++++++++++++++++++++------ src/config.rs | 2 ++ 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9748c05..c0e4376 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1421,7 +1421,7 @@ dependencies = [ [[package]] name = "modality-trace-recorder-plugin" -version = "0.9.0" +version = "0.10.0" dependencies = [ "async-trait", "byteordered", diff --git a/Cargo.toml b/Cargo.toml index 3e3e910..471c4d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "modality-trace-recorder-plugin" -version = "0.9.0" +version = "0.10.0" edition = "2021" authors = ["Jon Lamb "] description = "A Modality reflector plugin suite and ingest adapter library for Percepio's TraceRecorder data" diff --git a/src/bin/rtt_collector.rs b/src/bin/rtt_collector.rs index 67ec2c6..7639030 100644 --- a/src/bin/rtt_collector.rs +++ b/src/bin/rtt_collector.rs @@ -7,8 +7,8 @@ use modality_trace_recorder_plugin::{ use probe_rs::{ config::MemoryRegion, probe::{list::Lister, DebugProbeSelector, WireProtocol}, - rtt::{Rtt, UpChannel}, - Core, Permissions, Session, + rtt::{Rtt, ScanRegion, UpChannel}, + Core, Permissions, Session, VectorCatchCondition, }; use std::{ fs, io, @@ -41,6 +41,14 @@ struct Opts { )] pub attach_timeout: Option, + /// Use the provided RTT control block address instead of scanning the target memory for it. + #[clap( + long, + name = "control-block-address", + help_heading = "STREAMING PORT CONFIGURATION" + )] + pub control_block_address: Option, + /// Disable sending control plane commands to the target. /// By default, CMD_SET_ACTIVE is sent on startup and shutdown to /// start and stop tracing on the target. @@ -167,6 +175,9 @@ async fn do_main() -> Result<(), Box> { if let Some(to) = opts.attach_timeout { trc_cfg.plugin.rtt_collector.attach_timeout = Some(to.into()); } + if let Some(addr) = opts.control_block_address { + trc_cfg.plugin.rtt_collector.control_block_address = addr.into(); + } if opts.disable_control_plane { trc_cfg.plugin.rtt_collector.disable_control_plane = true; } @@ -231,12 +242,6 @@ async fn do_main() -> Result<(), Box> { probe.select_protocol(trc_cfg.plugin.rtt_collector.protocol)?; probe.set_speed(trc_cfg.plugin.rtt_collector.speed)?; - if trc_cfg.plugin.rtt_collector.reset { - debug!("Reseting target"); - probe.target_reset_assert()?; - probe.target_reset_deassert()?; - } - debug!( chip = chip, core = trc_cfg.plugin.rtt_collector.core, @@ -244,17 +249,47 @@ async fn do_main() -> Result<(), Box> { ); let mut session = probe.attach(chip, Permissions::default())?; + let rtt_scan_regions = session.target().rtt_scan_regions.clone(); + let mut rtt_scan_region = if rtt_scan_regions.is_empty() { + ScanRegion::Ram + } else { + ScanRegion::Ranges(rtt_scan_regions) + }; + if let Some(user_provided_addr) = trc_cfg.plugin.rtt_collector.control_block_address { + debug!( + rtt_addr = user_provided_addr, + "Using explicit RTT control block address" + ); + rtt_scan_region = ScanRegion::Exact(user_provided_addr); + } + let memory_map = session.target().memory_map.clone(); let mut core = session.core(trc_cfg.plugin.rtt_collector.core)?; + if trc_cfg.plugin.rtt_collector.reset { + debug!("Reset and halt core"); + core.reset_and_halt(Duration::from_millis(100))?; + } + + // Disable any previous vector catching (i.e. user just ran probe-rs run or a debugger) + core.disable_vector_catch(VectorCatchCondition::All)?; + core.clear_all_hw_breakpoints()?; + let mut rtt = match trc_cfg.plugin.rtt_collector.attach_timeout { - Some(to) if !to.0.is_zero() => attach_retry_loop(&mut core, &memory_map, to.0)?, + Some(to) if !to.0.is_zero() => { + attach_retry_loop(&mut core, &memory_map, &rtt_scan_region, to.0)? + } _ => { debug!("Attaching to RTT"); Rtt::attach(&mut core, &memory_map)? } }; + if trc_cfg.plugin.rtt_collector.reset { + debug!("Run core"); + core.run()?; + } + let up_channel = rtt .up_channels() .take(trc_cfg.plugin.rtt_collector.up_channel) @@ -350,13 +385,14 @@ async fn do_main() -> Result<(), Box> { fn attach_retry_loop( core: &mut Core, memory_map: &[MemoryRegion], + scan_region: &ScanRegion, timeout: humantime::Duration, ) -> Result { debug!(timeout = %timeout, "Attaching to RTT"); let timeout: Duration = timeout.into(); let start = Instant::now(); while Instant::now().duration_since(start) <= timeout { - match Rtt::attach(core, memory_map) { + match Rtt::attach_region(core, memory_map, scan_region) { Ok(rtt) => return Ok(rtt), Err(e) => { if matches!(e, probe_rs::rtt::Error::ControlBlockNotFound) { @@ -428,6 +464,19 @@ impl io::Read for TrcRttReader { .read(&mut core, &mut buf[bytes_fulfilled..]) .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?; bytes_fulfilled += rtt_bytes_read; + + // NOTE: this is what probe-rs does + // + // Poll RTT with a frequency of 10 Hz if we do not receive any new data. + // Once we receive new data, we bump the frequency to 1kHz. + // + // If the polling frequency is too high, the USB connection to the probe + // can become unstable. Hence we only pull as little as necessary. + if rtt_bytes_read != 0 { + std::thread::sleep(Duration::from_millis(1)); + } else { + std::thread::sleep(Duration::from_millis(100)); + } } Ok(bytes_fulfilled) diff --git a/src/config.rs b/src/config.rs index ecfe7d1..cac3a87 100644 --- a/src/config.rs +++ b/src/config.rs @@ -120,6 +120,7 @@ impl Default for ItmCollectorConfig { #[serde(rename_all = "kebab-case", default)] pub struct RttCollectorConfig { pub attach_timeout: Option, + pub control_block_address: Option, pub disable_control_plane: bool, pub restart: bool, pub up_channel: usize, @@ -145,6 +146,7 @@ impl Default for RttCollectorConfig { fn default() -> Self { Self { attach_timeout: None, + control_block_address: None, disable_control_plane: false, restart: false, up_channel: Self::DEFAULT_UP_CHANNEL,