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