Repository: probe-rs/probe-rs
Pull request #3344 (2025-05-19 07:29:56)

target-gen: support specifying a probe for testing
Support specifying --probe when doing `target-gen test`. This enables generating flash algorithms when there are multiple probes attached to a system, or when one probe has multiple drivers.


Patch:
diff --git a/changelog/added-endian-definition.md b/changelog/added-endian-definition.md
new file mode 100644
index 00000000..7de30f9d
--- /dev/null
+++ b/changelog/added-endian-definition.md
@@ -0,0 +1,1 @@
+Added an `Endian` enum and an `.endianness()` call on `CoreInterface`
diff --git a/changelog/added-probe-argument-to-target-gen.md b/changelog/added-probe-argument-to-target-gen.md
new file mode 100644
index 00000000..02bce6a3
--- /dev/null
+++ b/changelog/added-probe-argument-to-target-gen.md
@@ -0,0 +1,1 @@
+Added `--probe` to the `test` verb for `target-gen`
diff --git a/probe-rs-target/src/chip_family.rs b/probe-rs-target/src/chip_family.rs
index 18003dc1..0e2bb31d 100644
--- a/probe-rs-target/src/chip_family.rs
+++ b/probe-rs-target/src/chip_family.rs
@@ -173,6 +173,15 @@ impl InstructionSet {
     }
 }
 
+/// The current endianness of a core
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
+pub enum Endian {
+    /// Little endian mode -- this is the most common mode
+    Little,
+    /// Big endian mode -- this is common on network hardware
+    Big,
+}
+
 /// This describes a chip family with all its variants.
 ///
 /// This struct is usually read from a target description
diff --git a/probe-rs-target/src/lib.rs b/probe-rs-target/src/lib.rs
index 3609dbf0..00343705 100644
--- a/probe-rs-target/src/lib.rs
+++ b/probe-rs-target/src/lib.rs
@@ -23,7 +23,7 @@ pub use chip::{
     RiscvJtagTunnel, ScanChainElement, XtensaCoreAccessOptions,
 };
 pub use chip_family::{
-    Architecture, ChipFamily, CoreType, InstructionSet, TargetDescriptionSource,
+    Architecture, ChipFamily, CoreType, Endian, InstructionSet, TargetDescriptionSource,
 };
 pub use flash_algorithm::{RawFlashAlgorithm, TransferEncoding};
 pub use flash_properties::FlashProperties;
diff --git a/probe-rs/src/config/mod.rs b/probe-rs/src/config/mod.rs
index 6713e6bc..f6a3dc25 100644
--- a/probe-rs/src/config/mod.rs
+++ b/probe-rs/src/config/mod.rs
@@ -27,9 +27,9 @@ pub(crate) mod registry;
 mod target;
 
 pub use probe_rs_target::{
-    Chip, ChipFamily, Core, CoreType, FlashProperties, GenericRegion, InstructionSet, MemoryAccess,
-    MemoryRange, MemoryRegion, NvmRegion, PageInfo, RamRegion, RawFlashAlgorithm, ScanChainElement,
-    SectorDescription, SectorInfo, TargetDescriptionSource,
+    Chip, ChipFamily, Core, CoreType, Endian, FlashProperties, GenericRegion, InstructionSet,
+    MemoryAccess, MemoryRange, MemoryRegion, NvmRegion, PageInfo, RamRegion, RawFlashAlgorithm,
+    ScanChainElement, SectorDescription, SectorInfo, TargetDescriptionSource,
 };
 
 pub use registry::{Registry, RegistryError};
diff --git a/probe-rs/src/core.rs b/probe-rs/src/core.rs
index cbee6d4d..82ca1a28 100644
--- a/probe-rs/src/core.rs
+++ b/probe-rs/src/core.rs
@@ -1,5 +1,5 @@
 use crate::{
-    CoreType, InstructionSet, MemoryInterface, Target,
+    CoreType, Endian, InstructionSet, MemoryInterface, Target,
     architecture::{
         arm::sequences::ArmDebugSequence, riscv::sequences::RiscvDebugSequence,
         xtensa::sequences::XtensaDebugSequence,
@@ -132,6 +132,13 @@ pub trait CoreInterface: MemoryInterface {
     /// decision for some core types
     fn instruction_set(&mut self) -> Result<InstructionSet, Error>;
 
+    /// Return which endianness the core is currently in. Some cores
+    /// allow for changing the endianness.
+    fn endianness(&mut self) -> Result<Endian, Error> {
+        // Return little endian, since that is the most common mode by far.
+        Ok(Endian::Little)
+    }
+
     /// Determine if an FPU is present.
     /// This must be queried while halted as this is a runtime
     /// decision for some core types.
diff --git a/probe-rs/src/lib.rs b/probe-rs/src/lib.rs
index 8739f4f3..c9f94641 100644
--- a/probe-rs/src/lib.rs
+++ b/probe-rs/src/lib.rs
@@ -87,7 +87,7 @@ mod session;
 #[cfg(any(test, feature = "test"))]
 pub mod test;
 
-pub use crate::config::{CoreType, InstructionSet, Target};
+pub use crate::config::{CoreType, Endian, InstructionSet, Target};
 pub use crate::core::dump::CoreDump;
 pub use crate::core::dump::CoreDumpError;
 pub use crate::core::registers::RegisterDataType;
diff --git a/target-gen/src/main.rs b/target-gen/src/main.rs
index 30d3b8a7..394666fc 100644
--- a/target-gen/src/main.rs
+++ b/target-gen/src/main.rs
@@ -1,6 +1,6 @@
 use anyhow::{Context, Result, ensure};
 use clap::Parser;
-use probe_rs::probe::WireProtocol;
+use probe_rs::probe::{DebugProbeSelector, WireProtocol};
 use probe_rs_target::ChipFamily;
 use std::{
     env::current_dir,
@@ -105,6 +105,12 @@ enum TargetGen {
         /// Name of the flash algorithm to test
         #[clap(long = "name", short = 'n')]
         name: Option<String>,
+        /// Use this flag to select a specific probe in the list.
+        ///
+        /// Use '--probe VID:PID' or '--probe VID:PID:Serial' if you have more than one
+        /// probe with the same VID:PID.",
+        #[arg(long)]
+        probe: Option<DebugProbeSelector>,
         /// Speed to run the probe at
         #[clap(long = "speed", default_value = None)]
         speed: Option<u32>,
@@ -167,6 +173,7 @@ async fn main() -> Result<()> {
             name,
             speed,
             protocol,
+            probe,
         } => cmd_test(
             target_artifact.as_path(),
             template_path.as_path(),
@@ -174,6 +181,7 @@ async fn main() -> Result<()> {
             test_start_sector_address,
             chip,
             name,
+            probe,
             speed,
             protocol,
         )?,


Test patch:
diff --git a/target-gen/src/commands/test.rs b/target-gen/src/commands/test.rs
index cf7d46e0..8da7259c 100644
--- a/target-gen/src/commands/test.rs
+++ b/target-gen/src/commands/test.rs
@@ -12,7 +12,7 @@ use probe_rs::{
         DownloadOptions, FlashLoader, FlashProgress, ProgressEvent, ProgressOperation, erase_all,
         erase_sectors,
     },
-    probe::WireProtocol,
+    probe::{DebugProbeSelector, WireProtocol, list::Lister},
 };
 use probe_rs_target::RawFlashAlgorithm;
 use xshell::{Shell, cmd};
@@ -27,6 +27,7 @@ pub fn cmd_test(
     test_start_sector_address: Option<u64>,
     chip: Option<String>,
     name: Option<String>,
+    probe: Option<DebugProbeSelector>,
     speed: Option<u32>,
     protocol: Option<WireProtocol>,
 ) -> Result<()> {
@@ -97,9 +98,30 @@ pub fn cmd_test(
         protocol,
     };
 
+    let lister = Lister::new();
+    let available_probes = lister.list(probe.as_ref());
+    if available_probes.len() > 1 {
+        return Err(anyhow!(
+            "Multiple probes were found -- please specify a probe with `--probe`"
+        ));
+    }
+    let Some(probe) = available_probes.first() else {
+        return Err(anyhow!("No probes were found"));
+    };
+    let mut probe = probe.open()?;
+
+    // If the caller has specified speed or protocol in SessionConfig, set them
+    if let Some(speed) = session_config.speed {
+        probe.set_speed(speed)?;
+    }
+
+    if let Some(protocol) = session_config.protocol {
+        probe.select_protocol(protocol)?;
+    }
+
     // We need to get the chip name so that special startup procedure can be used. (matched on name)
     let mut session =
-        probe_rs::Session::auto_attach_with_registry(target_name, session_config, &registry)?;
+        probe.attach_with_registry(target_name, session_config.permissions, &registry)?;
 
     // Register callback to update the progress.
     let t = Rc::new(RefCell::new(Instant::now()));