Skip to main content

probe_rs/probe/ch347usbjtag/
mod.rs

1//! ch347 is a usb bus converter that provides UART, I2C and SPI and Jtag/Swd interface
2mod protocol;
3
4use protocol::Ch347UsbJtagDevice;
5
6use crate::{
7    architecture::{
8        arm::{ArmCommunicationInterface, communication_interface::DapProbe},
9        riscv::dtm::jtag_dtm::JtagDtmBuilder,
10        xtensa::communication_interface::XtensaCommunicationInterface,
11    },
12    probe::{DebugProbe, ProbeFactory},
13};
14
15use super::{
16    AutoImplementJtagAccess, DebugProbeError, IoSequenceItem, JtagDriverState, RawJtagIo, RawSwdIo,
17    SwdSettings,
18};
19
20/// A factory for creating [`Ch347UsbJtag`] instances.
21#[derive(Debug)]
22pub struct Ch347UsbJtagFactory;
23
24impl std::fmt::Display for Ch347UsbJtagFactory {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        f.write_str("Ch347UsbJtag")
27    }
28}
29
30/// An Ch347-based debug probe.
31#[derive(Debug)]
32pub struct Ch347UsbJtag {
33    device: Ch347UsbJtagDevice,
34    jtag_state: JtagDriverState,
35    swd_settings: SwdSettings,
36}
37
38impl ProbeFactory for Ch347UsbJtagFactory {
39    fn open(
40        &self,
41        selector: &super::DebugProbeSelector,
42    ) -> Result<Box<dyn super::DebugProbe>, super::DebugProbeError> {
43        let ch347 = Ch347UsbJtagDevice::new_from_selector(selector)?;
44
45        tracing::info!("Found ch347 device");
46        Ok(Box::new(Ch347UsbJtag {
47            device: ch347,
48            jtag_state: JtagDriverState::default(),
49            swd_settings: SwdSettings::default(),
50        }))
51    }
52
53    fn list_probes(&self) -> Vec<super::list::ProbeListItem> {
54        protocol::list_ch347usbjtag_devices()
55    }
56}
57
58impl RawJtagIo for Ch347UsbJtag {
59    fn shift_bit(
60        &mut self,
61        tms: bool,
62        tdi: bool,
63        capture: bool,
64    ) -> Result<(), super::DebugProbeError> {
65        self.jtag_state.state.update(tms);
66        self.device.shift_bit(tms, tdi, capture)?;
67
68        Ok(())
69    }
70
71    fn read_captured_bits(&mut self) -> Result<bitvec::prelude::BitVec, super::DebugProbeError> {
72        self.device.read_captured_bits()
73    }
74
75    fn state_mut(&mut self) -> &mut JtagDriverState {
76        &mut self.jtag_state
77    }
78
79    fn state(&self) -> &JtagDriverState {
80        &self.jtag_state
81    }
82}
83
84impl RawSwdIo for Ch347UsbJtag {
85    fn swd_io<S>(&mut self, _swdio: S) -> Result<Vec<bool>, DebugProbeError>
86    where
87        S: IntoIterator<Item = IoSequenceItem>,
88    {
89        Err(DebugProbeError::NotImplemented {
90            function_name: "swd_io",
91        })
92    }
93
94    fn swj_pins(
95        &mut self,
96        _pin_out: u32,
97        _pin_select: u32,
98        _pin_wait: u32,
99    ) -> Result<u32, DebugProbeError> {
100        Err(DebugProbeError::CommandNotSupportedByProbe {
101            command_name: "swj_pins",
102        })
103    }
104
105    fn swd_settings(&self) -> &SwdSettings {
106        &self.swd_settings
107    }
108}
109
110impl AutoImplementJtagAccess for Ch347UsbJtag {}
111impl DapProbe for Ch347UsbJtag {}
112
113impl DebugProbe for Ch347UsbJtag {
114    fn get_name(&self) -> &str {
115        "CH347 USB Jtag"
116    }
117
118    fn speed_khz(&self) -> u32 {
119        self.device.speed_khz()
120    }
121
122    fn set_speed(&mut self, speed_khz: u32) -> Result<u32, super::DebugProbeError> {
123        Ok(self.device.set_speed_khz(speed_khz))
124    }
125
126    fn attach(&mut self) -> Result<(), super::DebugProbeError> {
127        self.device.attach()
128    }
129
130    fn detach(&mut self) -> Result<(), crate::Error> {
131        Ok(())
132    }
133
134    fn target_reset(&mut self) -> Result<(), super::DebugProbeError> {
135        // TODO
136        Err(DebugProbeError::NotImplemented {
137            function_name: "target_reset",
138        })
139    }
140    fn target_reset_assert(&mut self) -> Result<(), super::DebugProbeError> {
141        // TODO
142        Err(DebugProbeError::NotImplemented {
143            function_name: "target_reset_assert",
144        })
145    }
146
147    fn target_reset_deassert(&mut self) -> Result<(), super::DebugProbeError> {
148        // TODO
149        Err(DebugProbeError::NotImplemented {
150            function_name: "target_reset_deassert",
151        })
152    }
153
154    fn select_protocol(
155        &mut self,
156        protocol: super::WireProtocol,
157    ) -> Result<(), super::DebugProbeError> {
158        // ch347 is support swd, wait...
159        // TODO
160        if protocol != super::WireProtocol::Jtag {
161            Err(DebugProbeError::UnsupportedProtocol(protocol))
162        } else {
163            Ok(())
164        }
165    }
166
167    fn active_protocol(&self) -> Option<super::WireProtocol> {
168        // TODO
169        Some(super::WireProtocol::Jtag)
170    }
171
172    fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
173        self
174    }
175
176    fn try_as_jtag_probe(&mut self) -> Option<&mut dyn super::JtagAccess> {
177        Some(self)
178    }
179
180    fn has_arm_interface(&self) -> bool {
181        true
182    }
183
184    fn try_get_arm_debug_interface<'probe>(
185        self: Box<Self>,
186        sequence: std::sync::Arc<dyn crate::architecture::arm::sequences::ArmDebugSequence>,
187    ) -> Result<
188        Box<dyn crate::architecture::arm::ArmDebugInterface + 'probe>,
189        (Box<dyn DebugProbe>, crate::architecture::arm::ArmError),
190    > {
191        Ok(ArmCommunicationInterface::create(self, sequence, true))
192    }
193
194    fn has_riscv_interface(&self) -> bool {
195        true
196    }
197
198    fn try_get_riscv_interface_builder<'probe>(
199        &'probe mut self,
200    ) -> Result<
201        Box<
202            dyn crate::architecture::riscv::communication_interface::RiscvInterfaceBuilder<'probe>
203                + 'probe,
204        >,
205        crate::architecture::riscv::communication_interface::RiscvError,
206    > {
207        Ok(Box::new(JtagDtmBuilder::new(self)))
208    }
209
210    fn has_xtensa_interface(&self) -> bool {
211        true
212    }
213
214    fn try_get_xtensa_interface<'probe>(
215        &'probe mut self,
216        state: &'probe mut crate::architecture::xtensa::communication_interface::XtensaDebugInterfaceState,
217    ) -> Result<
218        crate::architecture::xtensa::communication_interface::XtensaCommunicationInterface<'probe>,
219        crate::architecture::xtensa::communication_interface::XtensaError,
220    > {
221        Ok(XtensaCommunicationInterface::new(self, state))
222    }
223}