dap_rs/
swd.rs

1use num_enum::{IntoPrimitive, TryFromPrimitive};
2
3/// The available errors for SWD.
4#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub enum Error {
7    /// Parity error.
8    BadParity,
9    /// Ack not yet ready.
10    AckWait,
11    /// A fault.
12    AckFault,
13    /// A protocol error.
14    AckProtocol,
15    /// Unkown error.
16    AckUnknown(u8),
17}
18
19/// The definision of SWD results.
20pub type Result<T> = core::result::Result<T, Error>;
21
22/// Available DP registers.
23#[repr(u8)]
24#[derive(PartialEq, Eq, Copy, Clone, Debug, IntoPrimitive, TryFromPrimitive)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26#[allow(missing_docs)]
27pub enum DPRegister {
28    DPIDR = 0,
29    CTRLSTAT = 1,
30    SELECT = 2,
31    RDBUFF = 3,
32}
33
34/// Encode if a transaction is for AP or DP.
35#[repr(u8)]
36#[derive(PartialEq, Eq, Copy, Clone, Debug, TryFromPrimitive)]
37#[cfg_attr(feature = "defmt", derive(defmt::Format))]
38pub enum APnDP {
39    /// For DP.
40    DP = 0,
41    /// For AP.
42    AP = 1,
43}
44
45/// Encode if an SWD transaction is a read or a write.
46#[repr(u8)]
47#[derive(PartialEq, Eq, Copy, Clone, Debug, TryFromPrimitive)]
48#[cfg_attr(feature = "defmt", derive(defmt::Format))]
49pub enum RnW {
50    /// Write flag.
51    W = 0,
52    /// Read flag.
53    R = 1,
54}
55
56/// The different kinds of SWD Ack.
57#[repr(u8)]
58#[derive(PartialEq, Eq, Copy, Clone, Debug)]
59#[cfg_attr(feature = "defmt", derive(defmt::Format))]
60#[allow(missing_docs)]
61pub enum Ack {
62    Ok = 0b001,
63    Wait = 0b010,
64    Fault = 0b100,
65    Protocol = 0b111,
66}
67
68impl Ack {
69    /// Helper method for `Swd::read_inner` and `Swd::write_inner` to decode an SWD Ack.
70    pub fn try_ok(ack: u8) -> Result<()> {
71        match ack {
72            v if v == (Ack::Ok as u8) => Ok(()),
73            v if v == (Ack::Wait as u8) => Err(Error::AckWait),
74            v if v == (Ack::Fault as u8) => Err(Error::AckFault),
75            v if v == (Ack::Protocol as u8) => Err(Error::AckProtocol),
76            _ => Err(Error::AckUnknown(ack)),
77        }
78    }
79}
80
81/// Turn around period configuration.
82#[derive(Copy, Clone, Debug, TryFromPrimitive, PartialEq, Eq)]
83#[cfg_attr(feature = "defmt", derive(defmt::Format))]
84#[allow(missing_docs)]
85#[repr(u8)]
86pub enum TurnaroundPeriod {
87    Cycles1 = 0b00,
88    Cycles2 = 0b01,
89    Cycles3 = 0b10,
90    Cycles4 = 0b11,
91}
92
93/// Data phase configuration.
94#[derive(Copy, Clone, Debug, TryFromPrimitive, PartialEq, Eq)]
95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96#[allow(missing_docs)]
97#[repr(u8)]
98pub enum DataPhase {
99    NoDataPhase = 0,
100    AlwaysDataPhase = 1,
101}
102
103/// Definition of SWD communication.
104pub trait Swd<DEPS>: From<DEPS> {
105    /// If SWD is available or not.
106    const AVAILABLE: bool;
107
108    /// Helper method over `read_inner` to retry during `AckWait`.
109    fn read(&mut self, wait_retries: usize, apndp: APnDP, a: DPRegister) -> Result<u32> {
110        for _ in 0..wait_retries {
111            match self.read_inner(apndp, a) {
112                Err(Error::AckWait) => continue,
113                x => return x,
114            }
115        }
116
117        Err(Error::AckWait)
118    }
119
120    /// Here the actual hardware implementation for an SWD read is made.
121    fn read_inner(&mut self, apndp: APnDP, a: DPRegister) -> Result<u32>;
122
123    /// Helper method over `write_inner` to retry during `AckWait`.
124    fn write(&mut self, wait_retries: usize, apndp: APnDP, a: DPRegister, data: u32) -> Result<()> {
125        for _ in 0..wait_retries {
126            match self.write_inner(apndp, a, data) {
127                Err(Error::AckWait) => continue,
128                x => return x,
129            }
130        }
131
132        Err(Error::AckWait)
133    }
134
135    /// Here the actual hardware implementation for an SWD write is made.
136    fn write_inner(&mut self, apndp: APnDP, a: DPRegister, data: u32) -> Result<()>;
137
138    /// Shorthand helper to read DP registers
139    fn read_dp(&mut self, wait_retries: usize, a: DPRegister) -> Result<u32> {
140        self.read(wait_retries, APnDP::DP, a)
141    }
142
143    /// Shorthand helper to write DP registers
144    fn write_dp(&mut self, wait_retries: usize, a: DPRegister, data: u32) -> Result<()> {
145        self.write(wait_retries, APnDP::DP, a, data)
146    }
147
148    /// Shorthand helper to read AP registers
149    fn read_ap(&mut self, wait_retries: usize, a: DPRegister) -> Result<u32> {
150        self.read(wait_retries, APnDP::AP, a)
151    }
152
153    /// Set the maximum clock frequency, return `true` if it is valid.
154    fn set_clock(&mut self, max_frequency: u32) -> bool;
155
156    /// Write a sequence of bits using SWDIO and the clock line running at the configured freq.
157    fn write_sequence(&mut self, num_bits: usize, data: &[u8]) -> Result<()>;
158
159    /// Read a sequence of bits using SWDIO and the clock line running at the configured freq.
160    fn read_sequence(&mut self, num_bits: usize, data: &mut [u8]) -> Result<()>;
161}
162
163/// Helper used by `Swd::read_inner` and `Swd::write_inner` to make the request byte.
164pub fn make_request(apndp: APnDP, rnw: RnW, a: DPRegister) -> u8 {
165    let req = 1 | ((apndp as u8) << 1) | ((rnw as u8) << 2) | ((a as u8) << 3) | (1 << 7);
166    let parity = (req.count_ones() & 1) as u8;
167    req | (parity << 5)
168}