libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
swd.hpp
1#pragma once
2
3#include <cstdint>
4
5#include "libxr_def.hpp"
6#include "swd_protocol.hpp"
7
8namespace LibXR::Debug
9{
16class Swd
17{
18 public:
31 {
32 uint8_t idle_cycles = 0;
33 uint16_t wait_retry = 100;
35 true;
36 };
37
41 virtual ~Swd() = default;
42
43 Swd(const Swd&) = delete;
44 Swd& operator=(const Swd&) = delete;
45
50 void SetTransferPolicy(const TransferPolicy& policy) { policy_ = policy; }
51
55 [[nodiscard]] const TransferPolicy& GetTransferPolicy() const { return policy_; }
56
62 virtual ErrorCode SetClockHz(uint32_t hz) = 0;
63
67 virtual void Close() = 0;
68
73 virtual ErrorCode LineReset() = 0;
74
80 virtual ErrorCode EnterSwd() = 0;
81
88 virtual ErrorCode Transfer(const SwdProtocol::Request& req,
89 SwdProtocol::Response& resp) = 0;
90
91 // --------------------------------------------------------------------------
92 // Retry wrapper
93 // --------------------------------------------------------------------------
94
112 {
113 ResetResponse(resp);
114
115 uint32_t retries = 0;
116
117 while (true)
118 {
119 auto ec = Transfer(req, resp);
120 if (ec != ErrorCode::OK)
121 {
122 resp.ack = SwdProtocol::Ack::PROTOCOL;
124 return ec;
125 }
126
127 // CMSIS-DAP IdleCycles:每次传输尝试后插入。CMSIS-DAP IdleCycles: insert after EACH
128 // transfer attempt.
129 if (policy_.idle_cycles != 0u)
130 {
132 }
133
134 if (resp.ack != SwdProtocol::Ack::WAIT)
135 {
136 break;
137 }
138 if (retries >= policy_.wait_retry)
139 {
140 break;
141 }
142 ++retries;
143 }
144
145 if (resp.ack != SwdProtocol::Ack::OK)
146 {
148 }
149
150 if (resp.ack == SwdProtocol::Ack::FAULT && policy_.clear_sticky_on_fault)
151 {
152 (void)ClearStickyErrors();
153 }
154
155 return ErrorCode::OK;
156 }
157
158 // --------------------------------------------------------------------------
159 // DP/AP helpers
160 // --------------------------------------------------------------------------
161
169 ErrorCode DpRead(SwdProtocol::DpReadReg reg, uint32_t& val, SwdProtocol::Ack& ack)
170 {
172 const ErrorCode EC = Transfer(SwdProtocol::make_dp_read_req(reg), resp);
173 if (EC != ErrorCode::OK)
174 {
175 ack = SwdProtocol::Ack::PROTOCOL;
176 return EC;
177 }
178
179 ack = resp.ack;
180
181 if (resp.ack != SwdProtocol::Ack::OK || !resp.parity_ok)
182 {
183 return ErrorCode::FAILED;
184 }
185
186 val = resp.rdata;
187 return ErrorCode::OK;
188 }
189
197 ErrorCode DpWrite(SwdProtocol::DpWriteReg reg, uint32_t val, SwdProtocol::Ack& ack)
198 {
200 const ErrorCode EC = Transfer(SwdProtocol::make_dp_write_req(reg, val), resp);
201 if (EC != ErrorCode::OK)
202 {
203 ack = SwdProtocol::Ack::PROTOCOL;
204 return EC;
205 }
206
207 ack = resp.ack;
208 return (resp.ack == SwdProtocol::Ack::OK) ? ErrorCode::OK : ErrorCode::FAILED;
209 }
210
218 ErrorCode DpReadTxn(SwdProtocol::DpReadReg reg, uint32_t& val, SwdProtocol::Ack& ack)
219 {
221 const ErrorCode EC = TransferWithRetry(SwdProtocol::make_dp_read_req(reg), resp);
222 ack = resp.ack;
223
224 if (EC != ErrorCode::OK)
225 {
226 return EC;
227 }
228
229 if (resp.ack != SwdProtocol::Ack::OK || !resp.parity_ok)
230 {
231 return ErrorCode::FAILED;
232 }
233
234 val = resp.rdata;
235 return ErrorCode::OK;
236 }
237
245 ErrorCode DpWriteTxn(SwdProtocol::DpWriteReg reg, uint32_t val, SwdProtocol::Ack& ack)
246 {
248 const ErrorCode EC =
249 TransferWithRetry(SwdProtocol::make_dp_write_req(reg, val), resp);
250 ack = resp.ack;
251
252 if (EC != ErrorCode::OK)
253 {
254 return EC;
255 }
256
257 return (resp.ack == SwdProtocol::Ack::OK) ? ErrorCode::OK : ErrorCode::FAILED;
258 }
259
274 ErrorCode ApReadTxn(uint8_t addr2b, uint32_t& val, SwdProtocol::Ack& ack)
275 {
277 const ErrorCode EC = TransferWithRetry(SwdProtocol::make_ap_read_req(addr2b), resp);
278 ack = resp.ack;
279
280 if (EC != ErrorCode::OK)
281 {
282 return EC;
283 }
284 if (resp.ack != SwdProtocol::Ack::OK)
285 {
286 return ErrorCode::FAILED;
287 }
288
289 return DpReadTxn(SwdProtocol::DpReadReg::RDBUFF, val, ack);
290 }
291
306 ErrorCode ApReadPostedTxn(uint8_t addr2b, uint32_t& posted_val, SwdProtocol::Ack& ack)
307 {
309 const ErrorCode EC = TransferWithRetry(SwdProtocol::make_ap_read_req(addr2b), resp);
310 ack = resp.ack;
311
312 if (EC != ErrorCode::OK)
313 {
314 return EC;
315 }
316 if (resp.ack != SwdProtocol::Ack::OK || !resp.parity_ok)
317 {
318 return ErrorCode::FAILED;
319 }
320
321 posted_val = resp.rdata;
322 return ErrorCode::OK;
323 }
324
331 ErrorCode DpReadRdbuffTxn(uint32_t& val, SwdProtocol::Ack& ack)
332 {
333 return DpReadTxn(SwdProtocol::DpReadReg::RDBUFF, val, ack);
334 }
335
343 ErrorCode ApWriteTxn(uint8_t addr2b, uint32_t val, SwdProtocol::Ack& ack)
344 {
346 const ErrorCode EC =
347 TransferWithRetry(SwdProtocol::make_ap_write_req(addr2b, val), resp);
348 ack = resp.ack;
349
350 if (EC != ErrorCode::OK)
351 {
352 return EC;
353 }
354
355 return (resp.ack == SwdProtocol::Ack::OK) ? ErrorCode::OK : ErrorCode::FAILED;
356 }
357
364 ErrorCode ReadIdCode(uint32_t& idcode, SwdProtocol::Ack& ack)
365 {
366 return DpRead(SwdProtocol::DpReadReg::IDCODE, idcode, ack);
367 }
368
375 ErrorCode WriteAbort(uint32_t flags, SwdProtocol::Ack& ack)
376 {
377 return DpWrite(SwdProtocol::DpWriteReg::ABORT, flags, ack);
378 }
379
386 ErrorCode WriteAbortTxn(uint32_t flags, SwdProtocol::Ack& ack)
387 {
388 return DpWriteTxn(SwdProtocol::DpWriteReg::ABORT, flags, ack);
389 }
390
391 // --------------------------------------------------------------------------
392 // SELECT cache
393 // --------------------------------------------------------------------------
394
402 ErrorCode SetSelectCached(uint32_t select, SwdProtocol::Ack& ack)
403 {
404 if (select_valid_ && (select_cache_ == select))
405 {
406 ack = SwdProtocol::Ack::OK;
407 return ErrorCode::OK;
408 }
409
410 const ErrorCode EC = DpWriteTxn(SwdProtocol::DpWriteReg::SELECT, select, ack);
411 if (EC == ErrorCode::OK && ack == SwdProtocol::Ack::OK)
412 {
413 select_cache_ = select;
414 select_valid_ = true;
415 }
416 return EC;
417 }
418
423 {
424 select_valid_ = false;
425 select_cache_ = 0u;
426 }
427
428 public:
432 Swd() = default;
433
438 virtual void IdleClocks(uint32_t cycles) = 0;
439
440 // 输出:在 SWDIO 上按 LSB-first 输出 data,并产生 SWCLK 脉冲。
441 // cycles: 位数(例如 1..256);data_lsb_first 长度 >= (cycles+7)/8
442 virtual ErrorCode SeqWriteBits(uint32_t cycles, const uint8_t* data_lsb_first) = 0;
443
444 // 输入:产生 SWCLK 脉冲并采样 SWDIO,按 LSB-first 写入 out_lsb_first。
445 // out_lsb_first 长度 >= (cycles+7)/8
446 virtual ErrorCode SeqReadBits(uint32_t cycles, uint8_t* out_lsb_first) = 0;
447
448 private:
453 static inline void ResetResponse(SwdProtocol::Response& resp)
454 {
455 resp.ack = SwdProtocol::Ack::PROTOCOL;
456 resp.rdata = 0u;
457 resp.parity_ok = true;
458 }
459
465 {
466 SwdProtocol::Ack ack = SwdProtocol::Ack::NO_ACK;
467 const uint32_t FLAGS =
468 SwdProtocol::DP_ABORT_STKCMPCLR | SwdProtocol::DP_ABORT_STKERRCLR |
469 SwdProtocol::DP_ABORT_WDERRCLR | SwdProtocol::DP_ABORT_ORUNERRCLR;
470 return DpWrite(SwdProtocol::DpWriteReg::ABORT, FLAGS, ack);
471 }
472
473 private:
475
476 uint32_t select_cache_ = 0u;
477 bool select_valid_ = false;
478};
479
480} // namespace LibXR::Debug
SWD 探针抽象基类,提供链路控制、传输与 DP/AP 辅助接口。 Abstract SWD probe base class providing link control,...
Definition swd.hpp:17
ErrorCode DpReadRdbuffTxn(uint32_t &val, SwdProtocol::Ack &ack)
读取 DP RDBUFF(带重试)。Read DP RDBUFF (with retry).
Definition swd.hpp:331
virtual ErrorCode SetClockHz(uint32_t hz)=0
设置 SWCLK 频率(可选)。Set SWCLK frequency (optional).
ErrorCode TransferWithRetry(const SwdProtocol::Request &req, SwdProtocol::Response &resp)
带重试的 SWD 传输封装(WAIT 重试 + IdleCycles 插入)。 SWD transfer wrapper with retry (WAIT retry + IdleCycles inse...
Definition swd.hpp:110
virtual ErrorCode LineReset()=0
执行 SWD 线复位。Perform SWD line reset.
ErrorCode WriteAbort(uint32_t flags, SwdProtocol::Ack &ack)
写入 DP ABORT(无重试)。Write DP ABORT (no retry).
Definition swd.hpp:375
ErrorCode WriteAbortTxn(uint32_t flags, SwdProtocol::Ack &ack)
写入 DP ABORT(带重试)。Write DP ABORT (with retry).
Definition swd.hpp:386
ErrorCode ReadIdCode(uint32_t &idcode, SwdProtocol::Ack &ack)
读取 DP IDCODE。Read DP IDCODE.
Definition swd.hpp:364
const TransferPolicy & GetTransferPolicy() const
获取传输策略。Get transfer policy.
Definition swd.hpp:55
Swd()=default
构造函数。Constructor.
ErrorCode ApReadTxn(uint8_t addr2b, uint32_t &val, SwdProtocol::Ack &ack)
AP 读事务(带重试,包含 RDBUFF 回读)。AP read transaction (with retry, with RDBUFF readback).
Definition swd.hpp:274
ErrorCode ClearStickyErrors()
清除 DP sticky 错误(尽力而为)。Clear DP sticky errors (best-effort).
Definition swd.hpp:464
virtual ~Swd()=default
虚析构函数。Virtual destructor.
ErrorCode ApWriteTxn(uint8_t addr2b, uint32_t val, SwdProtocol::Ack &ack)
AP 写事务(带重试)。AP write transaction (with retry).
Definition swd.hpp:343
void InvalidateSelectCache()
失效 SELECT 缓存。Invalidate SELECT cache.
Definition swd.hpp:422
ErrorCode DpWriteTxn(SwdProtocol::DpWriteReg reg, uint32_t val, SwdProtocol::Ack &ack)
DP 写事务(带重试)。DP write transaction (with retry).
Definition swd.hpp:245
static void ResetResponse(SwdProtocol::Response &resp)
重置响应结构体为默认值。Reset response to defaults.
Definition swd.hpp:453
virtual ErrorCode Transfer(const SwdProtocol::Request &req, SwdProtocol::Response &resp)=0
执行一次 SWD 传输(不含重试)。Perform one SWD transfer (no retry).
virtual ErrorCode EnterSwd()=0
进入 SWD 模式(如需从 JTAG 切换)。Enter SWD mode (e.g., switch from JTAG if needed).
ErrorCode DpWrite(SwdProtocol::DpWriteReg reg, uint32_t val, SwdProtocol::Ack &ack)
DP 寄存器写入(无重试)。DP register write (no retry).
Definition swd.hpp:197
virtual void Close()=0
关闭探针并释放资源。Close probe and release resources.
uint32_t select_cache_
SELECT 缓存值。SELECT cached value.
Definition swd.hpp:476
ErrorCode SetSelectCached(uint32_t select, SwdProtocol::Ack &ack)
写 SELECT(带缓存;命中则跳过写入)。Write SELECT with cache (skip write on hit).
Definition swd.hpp:402
ErrorCode DpRead(SwdProtocol::DpReadReg reg, uint32_t &val, SwdProtocol::Ack &ack)
DP 寄存器读取(无重试)。DP register read (no retry).
Definition swd.hpp:169
ErrorCode ApReadPostedTxn(uint8_t addr2b, uint32_t &posted_val, SwdProtocol::Ack &ack)
AP 读事务(带重试,不读 RDBUFF;返回 posted 数据)。 AP read transaction (with retry, no RDBUFF; returns posted data).
Definition swd.hpp:306
void SetTransferPolicy(const TransferPolicy &policy)
设置传输策略。Set transfer policy.
Definition swd.hpp:50
ErrorCode DpReadTxn(SwdProtocol::DpReadReg reg, uint32_t &val, SwdProtocol::Ack &ack)
DP 读事务(带重试)。DP read transaction (with retry).
Definition swd.hpp:218
TransferPolicy policy_
传输策略。Transfer policy.
Definition swd.hpp:474
virtual void IdleClocks(uint32_t cycles)=0
插入空闲时钟周期。Insert idle clock cycles.
bool select_valid_
SELECT 缓存是否有效。SELECT cache valid.
Definition swd.hpp:477
传输策略(WAIT 重试与空闲周期插入)。Transfer policy (WAIT retry & idle insertion).
Definition swd.hpp:31
uint8_t idle_cycles
空闲周期数。Idle cycles.
Definition swd.hpp:32
bool clear_sticky_on_fault
FAULT 时清除 sticky 错误。Clear sticky errors on FAULT.
Definition swd.hpp:34
uint16_t wait_retry
WAIT 最大重试次数。Maximum WAIT retries.
Definition swd.hpp:33
SWD 传输请求 / SWD transfer request.
SWD 传输响应 / SWD transfer response.
bool parity_ok
奇偶校验是否正确 / Whether parity is OK
uint32_t rdata
读数据(仅读响应有效)/ Read data (valid for read responses)