jaylink
jaylink copied to clipboard
Old JLink firmware expects some missing initialization step(s) to work correctly.
There's a second issue that I discovered yesterday with the same old JLink-OB clone probes.
Although probe is detected correctly after connection, it fails to work and reports the lack of response from target:
> ./list
Found 1 J-Link device.
Bus 006 Address 058 Port 004: VID=1366 PID=0101 – SEGGER J-Link (Serial 000000123456)
⤷ Capabilities: GetHwVersion | ReadConfig | WriteConfig | GetMaxBlockSize | GetHwInfo | ResetStopTimed | SelectIf | GetCounters | GetCpuCaps | ExecCpuCmd | Swo | Register | GetCapsEx
Firmware: J-Link ARM-OB STM32 compiled Aug 22 2012 19:52:04
HW Version: J-Link 7.0.0
Max. SWO Speed: 4500000 Hz
Max. Memblock: 11288 bytes
VTref: 3.3 V
Interfaces:
- JTAG (up to 12 MHz)
- SWD (up to 12 MHz)
> ./swdump
speed configuration: 12000 kHz
error: no response from target chip
> ./swdump
speed configuration: 12000 kHz
error: no response from target chip
Then I start and terminate (hit Ctrl+C) the official proprietary JLink tool (I want to get rid of this piece of non-free software, that's why I'm trying to learn how to use your library), it shows that both probe and target are OK:
> JLinkGDBServer -halt -if SWD -device STM32F030F4
SEGGER J-Link GDB Server V5.02f Command Line Version
JLinkARM.dll V5.02f (DLL compiled Oct 2 2015 20:53:57)
-----GDB Server start settings-----
GDBInit file: none
GDB Server Listening port: 2331
SWO raw output listening port: 2332
Terminal I/O port: 2333
Accept remote connection: yes
Generate logfile: off
Verify download: off
Init regs on start: off
Silent mode: off
Single run mode: off
Target connection timeout: 0 ms
------J-Link related settings------
J-Link Host interface: USB
J-Link script: none
J-Link settings file: none
------Target related settings------
Target device: STM32F030F4
Target interface: SWD
Target interface speed: 1000kHz
Target endian: little
Connecting to J-Link...
J-Link is connected.
Firmware: J-Link ARM-OB STM32 compiled Aug 22 2012 19:52:04
Hardware: V7.00
S/N: 20090928
Feature(s): RDI,FlashDL,FlashBP,JFlash,GDBFull
Checking target voltage...
Target voltage: 3.30 V
Listening on TCP/IP port 2331
Connecting to target...Connected to target
Waiting for GDB connection...^C
And then I run swdump again and... it works too:
> ./swdump
speed configuration: 12000 kHz
DPIDR=0x0BB11477
CTRL/STAT=0xF0000040
It works until I disconnect and connect my probe again, then I have to run JLinkGDBServer again. I know this report is incomplete without traces / USB communication dumps but probably someone saw this behavior too and already know the answer.
Might be because we don't register the connection https://github.com/jonas-schievink/jaylink/pull/26
Thank you, this is awesome! I took that PR, changed some lines to fix compilation errors (Capabilities -> Capability, REGISTER -> Register, etc) and it seems to be working now.
My diff
diff --git a/examples/swdump.rs b/examples/swdump.rs
index e1031cf..697c2b1 100644
--- a/examples/swdump.rs
+++ b/examples/swdump.rs
@@ -20,7 +20,7 @@
//!
//! This example assumes that the above "bug" (or misspecification?) is present.
-use jaylink::{Interface, JayLink, SpeedConfig};
+use jaylink::{Capability, Connection, Interface, JayLink, SpeedConfig};
use log::trace;
use std::{cmp, fmt};
use structopt::StructOpt;
@@ -300,6 +300,10 @@ fn run(opts: Opts) -> Result<(), SwdError> {
println!("speed configuration: {}", speed);
probe.set_speed(speed)?;
+ if probe.capabilities().contains(Capability::Register) {
+ probe.register(Connection::default())?;
+ }
+
probe.swj_seq()?;
let dpidr = probe.raw_read(Port::Debug, 0b0000)?;
diff --git a/src/lib.rs b/src/lib.rs
index d9e8fee..b5669d8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -93,7 +93,7 @@ pub use self::interface::{Interface, InterfaceIter, Interfaces};
use self::bits::IteratorExt as _;
use self::error::ResultExt as _;
use bitflags::bitflags;
-use byteorder::{LittleEndian, ReadBytesExt};
+use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
use io::Cursor;
use log::{debug, trace, warn};
use std::cell::{Cell, RefCell, RefMut};
@@ -162,6 +162,15 @@ enum Command {
ReadConfig = 0xF2,
WriteConfig = 0xF3,
+
+ Register = 0x09,
+}
+
+#[repr(u8)]
+#[allow(dead_code)]
+enum RegisterCommand {
+ Register = 0x64,
+ Unregister = 0x65,
}
#[repr(u8)]
@@ -208,6 +217,15 @@ impl SwoStatus {
}
}
+#[derive(Default, Debug)]
+pub struct Connection {
+ handle: u16,
+ pid: u32,
+ hid: Option<std::net::Ipv4Addr>,
+ iid: u8,
+ cid: u8,
+}
+
/// A handle to a J-Link USB device.
///
/// This is the main interface type of this library. There are multiple ways of obtaining an
@@ -628,7 +646,7 @@ impl JayLink {
///
/// This requires the probe to support [`Capability::SpeedInfo`].
pub fn read_speeds(&self) -> Result<SpeedInfo> {
- self.require_capability(Capability::SpeedInfo)?;
+ // self.require_capability(Capability::SpeedInfo)?;
self.write_cmd(&[Command::GetSpeeds as u8])?;
@@ -882,6 +900,30 @@ impl JayLink {
Ok(())
}
+ /// Registers a connection on the device.
+ ///
+ /// This requires the probe to support [`Capability::Register`].
+ ///
+ /// **Note**: This may be **required** on some devices for SWD to work at all.
+ ///
+ /// [`REGISTER`]: Capabilities::REGISTER
+ pub fn register(&self, conn: Connection) -> Result<()> {
+ self.require_capability(Capability::Register)?;
+ let mut buf = Vec::with_capacity(14);
+ buf.push(Command::Register as u8);
+ buf.push(RegisterCommand::Register as u8);
+ buf.write_u32::<LittleEndian>(conn.pid).unwrap();
+ buf.write_u32::<BigEndian>(conn.hid.unwrap_or(std::net::Ipv4Addr::LOCALHOST).into())
+ .unwrap();
+ buf.push(conn.iid);
+ buf.push(conn.cid);
+ buf.write_u16::<LittleEndian>(conn.handle).unwrap();
+ self.write_cmd(&buf)?;
+ let mut buf = [0; 76];
+ self.read(&mut buf)?;
+ Ok(())
+ }
+
/// Performs a JTAG I/O operation.
///
/// This will shift out data on `TMS` (pin 7) and `TDI` (pin 5), while reading data shifted
Should I close this issue now or it's better to wait until #26 is prettified and merged?
~~Not hard failing require_capability(Capability::SpeedInfo) (as you've done in this patch) should be also done somewhere I guess…~~ ah this is tracked as #35