jaylink/
interface.rs

1#![allow(non_upper_case_globals)]
2
3use std::fmt;
4
5enum_and_set!(
6    /// List of target interfaces.
7    ///
8    /// Note that this library might not support all of them, despite listing them here.
9    #[non_exhaustive]
10    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
11    pub enum Interface {
12        /// JTAG interface (IEEE 1149.1). Supported by most J-Link probes (some embedded J-Links might
13        /// only support SWD).
14        Jtag = 0,
15        /// SWD interface (Serial Wire Debug), used by most Cortex-M chips, and supported by almost all
16        /// J-Link probes.
17        Swd = 1,
18        /// Background Debug Mode 3, a single-wire debug interface used on some NXP microcontrollers.
19        Bdm3 = 2,
20        /// FINE, a two-wire debugging interface used by Renesas RX MCUs.
21        ///
22        /// **Note**: due to a bug, attempting to select FINE with [`JayLink::select_inferface`] will
23        /// currently hang the probe.
24        ///
25        /// [`JayLink::select_inferface`]: crate::JayLink::select_interface
26        // FIXME: There's a curious bug that hangs the probe when selecting the FINE interface.
27        // Specifically, the probe never sends back the previous interface after it receives the `c7 03`
28        // SELECT_IF cmd, even though the normal J-Link software also just sends `c7 03` and gets back
29        // the right response.
30        Fine = 3,
31        /// In-Circuit System Programming (ICSP) interface of PIC32 chips.
32        Pic32Icsp = 4,
33        /// Serial Peripheral Interface (for SPI Flash programming).
34        Spi = 5,
35        /// Silicon Labs' 2-wire debug interface.
36        C2 = 6,
37        /// [cJTAG], or compact JTAG, as specified in IEEE 1149.7.
38        ///
39        /// [cJTAG]: https://wiki.segger.com/J-Link_cJTAG_specifics.
40        CJtag = 7,
41        /// 2-wire debugging interface used by Microchip's IS208x MCUs.
42        Mc2WireJtag = 10,
43        // (*)
44        // NOTE: When changing this enum, also change all other places with a (*) in addition to
45        // anything that fails to compile.
46        // NOTE 2: Keep the docs in sync with the bitflags below!
47    }
48
49    flags InterfaceFlags: u32;
50);
51
52impl Interface {
53    pub(crate) fn as_u8(self) -> u8 {
54        self as u8
55    }
56}
57
58impl fmt::Display for Interface {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        f.write_str(match self {
61            Interface::Jtag => "JTAG",
62            Interface::Swd => "SWD",
63            Interface::Bdm3 => "BDM3",
64            Interface::Fine => "FINE",
65            Interface::Pic32Icsp => "PIC32 ICSP",
66            Interface::Spi => "SPI",
67            Interface::C2 => "C2",
68            Interface::CJtag => "cJTAG",
69            Interface::Mc2WireJtag => "Microchip 2-wire JTAG",
70        })
71    }
72}
73
74impl InterfaceFlags {
75    fn from_interface(interface: Interface) -> Self {
76        InterfaceFlags::from_bits(1 << interface as u32).unwrap()
77    }
78}
79
80/// A set of supported target interfaces.
81///
82/// This implements `IntoIterator`, so you can call `.into_iter()` to iterate over the contained
83/// [`Interface`]s.
84#[derive(Copy, Clone, Eq, PartialEq)]
85pub struct Interfaces(InterfaceFlags);
86
87impl Interfaces {
88    pub(crate) fn from_bits_warn(raw: u32) -> Self {
89        let flags = InterfaceFlags::from_bits_truncate(raw);
90        if flags.bits() != raw {
91            log::debug!(
92                "unknown bits in interface mask: 0x{:08X} truncated to 0x{:08X} ({:?})",
93                raw,
94                flags.bits(),
95                flags,
96            );
97        }
98        Self(flags)
99    }
100
101    pub(crate) fn single(interface: Interface) -> Self {
102        Self(InterfaceFlags::from_interface(interface))
103    }
104
105    /// Returns whether `interface` is contained in `self`.
106    pub fn contains(&self, interface: Interface) -> bool {
107        self.0.contains(InterfaceFlags::from_interface(interface))
108    }
109}
110
111impl fmt::Debug for Interfaces {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        self.0.fmt(f)
114    }
115}
116
117impl IntoIterator for Interfaces {
118    type Item = Interface;
119    type IntoIter = InterfaceIter;
120
121    fn into_iter(self) -> Self::IntoIter {
122        InterfaceIter {
123            interfaces: self,
124            next: 0,
125        }
126    }
127}
128
129/// Iterator over supported [`Interface`]s.
130#[derive(Debug)]
131pub struct InterfaceIter {
132    interfaces: Interfaces,
133    next: usize,
134}
135
136impl Iterator for InterfaceIter {
137    type Item = Interface;
138
139    fn next(&mut self) -> Option<Self::Item> {
140        loop {
141            let next = Interface::ALL.get(self.next)?;
142            self.next += 1;
143            if self.interfaces.contains(*next) {
144                return Some(*next);
145            }
146        }
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153
154    #[test]
155    fn iter() {
156        assert_eq!(
157            Interfaces(InterfaceFlags::empty())
158                .into_iter()
159                .collect::<Vec<_>>(),
160            &[]
161        );
162        assert_eq!(
163            Interfaces(InterfaceFlags::Jtag)
164                .into_iter()
165                .collect::<Vec<_>>(),
166            &[Interface::Jtag]
167        );
168        assert_eq!(
169            Interfaces(InterfaceFlags::Swd)
170                .into_iter()
171                .collect::<Vec<_>>(),
172            &[Interface::Swd]
173        );
174        assert_eq!(
175            Interfaces(InterfaceFlags::Jtag | InterfaceFlags::Swd)
176                .into_iter()
177                .collect::<Vec<_>>(),
178            &[Interface::Jtag, Interface::Swd]
179        );
180    }
181}