Skip to main content

probe_rs/probe/glasgow/
mod.rs

1//! Glasgow Interface Explorer probe implementation.
2//!
3//! This implementation is compatible with the `probe-rs` applet. The Glasgow toolkit must first
4//! be used to build the bitstream and configure the device; probe-rs cannot do that itself.
5
6use std::sync::Arc;
7
8use crate::architecture::arm::{
9    ArmCommunicationInterface, ArmDebugInterface, ArmError, DapError, RawDapAccess,
10    RegisterAddress,
11    communication_interface::DapProbe,
12    dp::{DpRegister, RdBuff},
13    sequences::ArmDebugSequence,
14};
15
16use super::{
17    DebugProbe, DebugProbeError, DebugProbeInfo, DebugProbeSelector, ProbeFactory, WireProtocol,
18    list::ProbeListItem,
19};
20
21mod mux;
22mod net;
23mod proto;
24mod usb;
25
26use mux::GlasgowDevice;
27use proto::Target;
28
29/// A factory for creating [`Glasgow`] probes.
30#[derive(Debug)]
31pub struct GlasgowFactory;
32
33impl std::fmt::Display for GlasgowFactory {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        f.write_str("Glasgow")
36    }
37}
38
39impl ProbeFactory for GlasgowFactory {
40    fn open(&self, selector: &DebugProbeSelector) -> Result<Box<dyn DebugProbe>, DebugProbeError> {
41        tracing::debug!("open({selector:?}");
42        Glasgow::new_from_device(GlasgowDevice::new_from_selector(selector)?)
43            .map(Box::new)
44            .map(DebugProbe::into_probe)
45    }
46
47    fn list_probes(&self) -> Vec<ProbeListItem> {
48        // Don't return anything; we don't know whether any given device is running a compatible
49        // bitstream, and there is no way for us to know which interfaces are bound to the probe-rs
50        // applet. These parameters must be specified by the user.
51        Vec::new()
52    }
53
54    fn list_probes_filtered(&self, selector: Option<&DebugProbeSelector>) -> Vec<ProbeListItem> {
55        // Return exactly the specified probe, if it has the option string (which is referred to
56        // here as the serial number).
57        if let Some(DebugProbeSelector {
58            vendor_id,
59            product_id,
60            serial_number: serial_number @ Some(_),
61            interface,
62        }) = selector
63            && *vendor_id == usb::VID_QIHW
64            && *product_id == usb::PID_GLASGOW
65        {
66            // The probe is built from the selector, so there is no enumerated device to check
67            // accessibility against here.
68            return vec![ProbeListItem::accessible(DebugProbeInfo {
69                identifier: "Glasgow".to_owned(),
70                vendor_id: *vendor_id,
71                product_id: *product_id,
72                serial_number: serial_number.clone(),
73                is_hid_interface: false,
74                probe_factory: &Self,
75                interface: *interface,
76            })];
77        }
78
79        vec![]
80    }
81}
82
83impl GlasgowDevice {
84    fn identify(&mut self) -> Result<(), DebugProbeError> {
85        self.send(Target::Root, &[proto::root::CMD_IDENTIFY]);
86        let identifier = self.recv(Target::Root, proto::root::IDENTIFIER.len())?;
87        let utf8_identifier = String::from_utf8_lossy(&identifier);
88        tracing::debug!("identify(): {utf8_identifier}");
89        if identifier == proto::root::IDENTIFIER {
90            Ok(())
91        } else {
92            Err(DebugProbeError::Other(format!(
93                "unsupported probe: {utf8_identifier:?}"
94            )))?
95        }
96    }
97
98    fn get_ref_clock(&mut self) -> Result<u32, DebugProbeError> {
99        self.send(Target::Root, &[proto::root::CMD_GET_REF_CLOCK]);
100        Ok(u32::from_le_bytes(
101            self.recv(Target::Root, 4)?.try_into().unwrap(),
102        ))
103    }
104
105    fn get_divisor(&mut self) -> Result<u16, DebugProbeError> {
106        self.send(Target::Root, &[proto::root::CMD_GET_DIVISOR]);
107        Ok(u16::from_le_bytes(
108            self.recv(Target::Root, 2)?.try_into().unwrap(),
109        ))
110    }
111
112    fn set_divisor(&mut self, divisor: u16) -> Result<(), DebugProbeError> {
113        self.send(Target::Root, &[proto::root::CMD_SET_DIVISOR]);
114        self.send(Target::Root, &u16::to_le_bytes(divisor));
115        Ok(())
116    }
117
118    fn assert_reset(&mut self) -> Result<(), DebugProbeError> {
119        self.send(Target::Root, &[proto::root::CMD_ASSERT_RESET]);
120        self.recv(Target::Root, 0)?;
121        Ok(())
122    }
123
124    fn clear_reset(&mut self) -> Result<(), DebugProbeError> {
125        self.send(Target::Root, &[proto::root::CMD_CLEAR_RESET]);
126        self.recv(Target::Root, 0)?;
127        Ok(())
128    }
129
130    fn swd_sequence(&mut self, len: u8, bits: u32) -> Result<(), DebugProbeError> {
131        assert!(len > 0 && len <= 32);
132        self.send(
133            Target::Swd,
134            &[proto::swd::CMD_SEQUENCE | (len & proto::swd::SEQ_LEN_MASK)],
135        );
136        self.send(Target::Swd, &bits.to_le_bytes()[..]);
137        self.recv(Target::Swd, 0)?;
138        Ok(())
139    }
140
141    fn swd_batch_cmd(&mut self, addr: RegisterAddress, data: Option<u32>) -> Result<(), ArmError> {
142        self.send(
143            Target::Swd,
144            &[proto::swd::CMD_TRANSFER
145                | (addr.is_ap() as u8)
146                | (data.is_none() as u8) << 1
147                | (addr.lsb() & 0b1100)],
148        );
149        if let Some(data) = data {
150            self.send(Target::Swd, &data.to_le_bytes()[..]);
151        }
152        Ok(())
153    }
154
155    fn swd_batch_ack(&mut self) -> Result<Option<u32>, ArmError> {
156        let response = self.recv(Target::Swd, 1)?[0];
157        if response & proto::swd::RSP_TYPE_MASK == proto::swd::RSP_TYPE_DATA {
158            Ok(Some(u32::from_le_bytes(
159                self.recv(Target::Swd, 4)?.try_into().unwrap(),
160            )))
161        } else if response & proto::swd::RSP_TYPE_MASK == proto::swd::RSP_TYPE_NO_DATA {
162            if response & proto::swd::RSP_ACK_MASK == proto::swd::RSP_ACK_OK {
163                Ok(None)
164            } else if response & proto::swd::RSP_ACK_MASK == proto::swd::RSP_ACK_WAIT {
165                Err(DapError::WaitResponse)?
166            } else if response & proto::swd::RSP_ACK_MASK == proto::swd::RSP_ACK_FAULT {
167                Err(DapError::FaultResponse)?
168            } else {
169                unreachable!()
170            }
171        } else if response & proto::swd::RSP_TYPE_MASK == proto::swd::RSP_TYPE_ERROR {
172            Err(DapError::Protocol(WireProtocol::Swd))?
173        } else {
174            unreachable!()
175        }
176    }
177}
178
179/// A Glasgow Interface Explorer device.
180pub struct Glasgow {
181    device: GlasgowDevice,
182    ref_clock: u32,
183    divisor: u16,
184}
185
186impl std::fmt::Debug for Glasgow {
187    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188        f.debug_struct("Glasgow").finish()
189    }
190}
191
192impl Glasgow {
193    fn new_from_device(mut device: GlasgowDevice) -> Result<Self, DebugProbeError> {
194        device.identify()?;
195        let ref_clock = device.get_ref_clock()?;
196        Ok(Glasgow {
197            device,
198            ref_clock,
199            divisor: 0,
200        })
201    }
202}
203
204impl DebugProbe for Glasgow {
205    fn get_name(&self) -> &str {
206        "Glasgow Interface Explorer"
207    }
208
209    fn speed_khz(&self) -> u32 {
210        proto::root::divisor_to_frequency(self.ref_clock, self.divisor) / 1000
211    }
212
213    fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError> {
214        tracing::debug!("set_speed({speed_khz})");
215        self.device.set_divisor(proto::root::frequency_to_divisor(
216            self.ref_clock,
217            speed_khz * 1000,
218        ))?;
219        self.divisor = self.device.get_divisor()?;
220        Ok(self.speed_khz())
221    }
222
223    fn attach(&mut self) -> Result<(), DebugProbeError> {
224        tracing::debug!("attach()");
225        Ok(())
226    }
227
228    fn detach(&mut self) -> Result<(), crate::Error> {
229        tracing::debug!("detach()");
230        Ok(())
231    }
232
233    fn target_reset(&mut self) -> Result<(), DebugProbeError> {
234        tracing::debug!("target_reset()");
235        Err(DebugProbeError::CommandNotSupportedByProbe {
236            command_name: "target_reset",
237        })
238    }
239
240    fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
241        tracing::debug!("target_reset_assert()");
242        self.device.assert_reset()
243    }
244
245    fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
246        tracing::debug!("target_reset_deassert()");
247        self.device.clear_reset()
248    }
249
250    fn active_protocol(&self) -> Option<super::WireProtocol> {
251        Some(WireProtocol::Swd)
252    }
253
254    fn select_protocol(&mut self, protocol: super::WireProtocol) -> Result<(), DebugProbeError> {
255        tracing::debug!("select_protocol({protocol})");
256        match protocol {
257            WireProtocol::Swd => Ok(()),
258            _ => Err(DebugProbeError::UnsupportedProtocol(protocol)),
259        }
260    }
261
262    fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
263        self
264    }
265
266    fn try_as_dap_probe(&mut self) -> Option<&mut dyn DapProbe> {
267        Some(self)
268    }
269
270    fn has_arm_interface(&self) -> bool {
271        true
272    }
273
274    fn try_get_arm_debug_interface<'probe>(
275        self: Box<Self>,
276        sequence: Arc<dyn ArmDebugSequence>,
277    ) -> Result<Box<dyn ArmDebugInterface + 'probe>, (Box<dyn DebugProbe>, ArmError)> {
278        // The Glasgow applet handles FAULT/WAIT states promptly.
279        Ok(ArmCommunicationInterface::create(
280            self, sequence, /*use_overrun_detect=*/ false,
281        ))
282    }
283}
284
285impl DapProbe for Glasgow {}
286
287impl RawDapAccess for Glasgow {
288    fn raw_read_register(&mut self, address: RegisterAddress) -> Result<u32, ArmError> {
289        if address.is_ap() {
290            let mut value = 0;
291            self.raw_read_block(address, std::slice::from_mut(&mut value))?;
292            Ok(value)
293        } else {
294            self.device.swd_batch_cmd(address, None)?;
295            let value = self.device.swd_batch_ack()?.expect("expected data");
296            tracing::debug!("raw_read_register({address:x?}) -> {value:x}");
297            Ok(value)
298        }
299    }
300
301    fn raw_read_block(
302        &mut self,
303        address: RegisterAddress,
304        values: &mut [u32],
305    ) -> Result<(), ArmError> {
306        assert!(address.is_ap());
307        for _ in 0..values.len() {
308            self.device.swd_batch_cmd(address, None)?;
309        }
310        self.device
311            .swd_batch_cmd(RegisterAddress::DpRegister(RdBuff::ADDRESS), None)?;
312        let _ = self.device.swd_batch_ack()?.expect("expected data");
313        for value in values.iter_mut() {
314            *value = self.device.swd_batch_ack()?.expect("expected data");
315        }
316        tracing::debug!(
317            "raw_read_block({address:x?}, {}) -> {values:x?}",
318            values.len()
319        );
320        Ok(())
321    }
322
323    fn raw_write_register(&mut self, address: RegisterAddress, value: u32) -> Result<(), ArmError> {
324        tracing::debug!("raw_write_register({address:x?}, {value:x})");
325        self.device.swd_batch_cmd(address, Some(value))?;
326        let response = self.device.swd_batch_ack()?;
327        assert!(response.is_none(), "unexpected data");
328        Ok(())
329    }
330
331    fn raw_write_block(
332        &mut self,
333        address: RegisterAddress,
334        values: &[u32],
335    ) -> Result<(), ArmError> {
336        tracing::debug!("raw_write_block({address:x?}, {values:x?})");
337        assert!(address.is_ap());
338        for value in values {
339            self.device.swd_batch_cmd(address, Some(*value))?;
340        }
341        for _ in 0..values.len() {
342            let response = self.device.swd_batch_ack()?;
343            assert!(response.is_none(), "unexpected data");
344        }
345        Ok(())
346    }
347
348    fn jtag_sequence(&mut self, cycles: u8, tms: bool, tdi: u64) -> Result<(), DebugProbeError> {
349        tracing::debug!("jtag_sequence({cycles}, {tms}, {tdi})");
350        Err(DebugProbeError::CommandNotSupportedByProbe {
351            command_name: "jtag_sequence",
352        })
353    }
354
355    fn swj_sequence(&mut self, len: u8, bits: u64) -> Result<(), DebugProbeError> {
356        tracing::debug!("swj_sequence({len}, {bits:#x})");
357        if len > 0 {
358            self.device.swd_sequence(len.min(32), bits as u32)?;
359        }
360        if len > 32 {
361            self.device.swd_sequence(len - 32, (bits >> 32) as u32)?;
362        }
363        Ok(())
364    }
365
366    fn swj_pins(
367        &mut self,
368        pin_out: u32,
369        pin_select: u32,
370        pin_wait: u32,
371    ) -> Result<u32, DebugProbeError> {
372        tracing::debug!("swj_pins({pin_out:#010b}, {pin_select:#010b}, {pin_wait:#010b})");
373        const PIN_NSRST: u32 = 0x80;
374        if pin_select != PIN_NSRST || pin_wait != 0 {
375            Err(DebugProbeError::CommandNotSupportedByProbe {
376                command_name: "swj_pins",
377            })
378        } else {
379            if pin_out & PIN_NSRST == 0 {
380                self.device.assert_reset()?;
381            } else {
382                self.device.clear_reset()?;
383            }
384            // Signal that we cannot read the pin state.
385            Ok(0xFFFF_FFFF)
386        }
387    }
388
389    fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
390        self
391    }
392
393    fn core_status_notification(
394        &mut self,
395        _state: crate::CoreStatus,
396    ) -> Result<(), DebugProbeError> {
397        Ok(())
398    }
399}