libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
daplink_v1.hpp
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <cstring>
6
7#include "daplink_v1_def.hpp"
8#include "debug/jtag_dp.hpp"
9#include "debug/swd.hpp"
10#include "gpio.hpp"
11#include "hid.hpp"
12#include "libxr_def.hpp"
13#include "libxr_mem.hpp"
14#include "libxr_type.hpp"
15#include "timebase.hpp"
16
17namespace LibXR::USB
18{
19#ifndef LIBXR_USB_DAPLINK_V1_BUILD_CONFIG_DEFINED
20#define LIBXR_USB_DAPLINK_V1_BUILD_CONFIG_DEFINED
21namespace DapLinkV1BuildConfig
22{
23static constexpr bool kEnableJtag = true;
24}
25#endif
26
27static constexpr uint8_t DAPLINK_V1_REPORT_DESC[] = {
28 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
29 0x09, 0x01, // Usage (0x01)
30 0xA1, 0x01, // Collection (Application)
31 0x15, 0x00, // Logical Minimum (0)
32 0x26, 0xFF, 0x00, // Logical Maximum (255)
33 0x75, 0x08, // Report Size (8)
34 0x95, 0x40, // Report Count (64)
35 0x09, 0x01, // Usage (0x01)
36 0x81, 0x02, // Input (Data, Variable, Absolute)
37 0x95, 0x40, // Report Count (64)
38 0x09, 0x01, // Usage (0x01)
39 0x91, 0x02, // Output (Data, Variable, Absolute)
40 0x95, 0x40, // Report Count (64)
41 0x09, 0x01, // Usage (0x01)
42 0xB1, 0x02, // Feature (Data, Variable, Absolute)
43 0xC0 // End Collection
44};
45
46template <typename SwdPort>
48 : public HID<sizeof(DAPLINK_V1_REPORT_DESC), DapLinkV1Def::MAX_REQUEST_SIZE,
49 DapLinkV1Def::MAX_RESPONSE_SIZE>
50{
51 public:
52 static constexpr bool JTAG_ENABLED = DapLinkV1BuildConfig::kEnableJtag;
53 static constexpr const char* DEFAULT_INTERFACE_STRING = "CMSIS-DAP";
55 {
56 const char* vendor = nullptr;
57 const char* product = nullptr;
58 const char* serial = nullptr;
59 const char* firmware_ver = nullptr;
60
61 const char* device_vendor = nullptr;
62 const char* device_name = nullptr;
63 const char* board_vendor = nullptr;
64 const char* board_name = nullptr;
65 const char* product_fw_ver = nullptr;
66 };
67
68 explicit DapLinkV1Class(Endpoint::EPNumber in_ep_num, Endpoint::EPNumber out_ep_num,
69 SwdPort& swd_link, LibXR::GPIO* nreset_gpio = nullptr);
70
71 ~DapLinkV1Class() override = default;
72
73 DapLinkV1Class(const DapLinkV1Class&) = delete;
74 DapLinkV1Class& operator=(const DapLinkV1Class&) = delete;
75
76 void SetInfoStrings(const InfoStrings& info);
77 void SetJtag(LibXR::Debug::Jtag* jtag);
78 const LibXR::USB::DapLinkV1Def::State& GetState() const;
79 bool IsInited() const;
80
81 protected:
83 ConstRawData GetReportDesc() override;
84
85 void BindEndpoints(EndpointPool& endpoint_pool, uint8_t start_itf_num,
86 bool in_isr) override;
87 void UnbindEndpoints(EndpointPool& endpoint_pool, bool in_isr) override;
88
89 void OnDataOutComplete(bool in_isr, LibXR::ConstRawData& data) override;
90 void OnDataInComplete(bool in_isr, LibXR::ConstRawData& data) override;
91
92 private:
93 static void OnDataOutCompleteStatic(bool in_isr, DapLinkV1Class* self,
95 static void OnDataInCompleteStatic(bool in_isr, DapLinkV1Class* self,
97
98 void ArmOutTransferIfIdle();
99
100 ErrorCode ProcessOneCommand(bool in_isr, const uint8_t* req, uint16_t req_len,
101 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
102 void BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
103
104 ErrorCode HandleInfo(bool in_isr, const uint8_t* req, uint16_t req_len, uint8_t* resp,
105 uint16_t resp_cap, uint16_t& out_len);
106 ErrorCode HandleHostStatus(bool in_isr, const uint8_t* req, uint16_t req_len,
107 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
108 ErrorCode HandleConnect(bool in_isr, const uint8_t* req, uint16_t req_len,
109 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
110 ErrorCode HandleDisconnect(bool in_isr, const uint8_t* req, uint16_t req_len,
111 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
112 ErrorCode HandleTransferConfigure(bool in_isr, const uint8_t* req, uint16_t req_len,
113 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
114 ErrorCode HandleTransfer(bool in_isr, const uint8_t* req, uint16_t req_len,
115 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
116 ErrorCode HandleTransferBlock(bool in_isr, const uint8_t* req, uint16_t req_len,
117 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
118 ErrorCode HandleTransferAbort(bool in_isr, const uint8_t* req, uint16_t req_len,
119 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
120 ErrorCode HandleWriteABORT(bool in_isr, const uint8_t* req, uint16_t req_len,
121 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
122 ErrorCode HandleDelay(bool in_isr, const uint8_t* req, uint16_t req_len, uint8_t* resp,
123 uint16_t resp_cap, uint16_t& out_len);
124 ErrorCode HandleResetTarget(bool in_isr, const uint8_t* req, uint16_t req_len,
125 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
126 ErrorCode HandleSWJPins(bool in_isr, const uint8_t* req, uint16_t req_len,
127 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
128 ErrorCode HandleSWJClock(bool in_isr, const uint8_t* req, uint16_t req_len,
129 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
130 ErrorCode HandleSWJSequence(bool in_isr, const uint8_t* req, uint16_t req_len,
131 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
132 ErrorCode HandleSWDConfigure(bool in_isr, const uint8_t* req, uint16_t req_len,
133 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
134 ErrorCode HandleSWDSequence(bool in_isr, const uint8_t* req, uint16_t req_len,
135 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
136 ErrorCode HandleJTAGSequence(bool in_isr, const uint8_t* req, uint16_t req_len,
137 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
138 ErrorCode HandleJTAGConfigure(bool in_isr, const uint8_t* req, uint16_t req_len,
139 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
140 ErrorCode HandleJTAGIdCode(bool in_isr, const uint8_t* req, uint16_t req_len,
141 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
142 ErrorCode HandleQueueCommands(bool in_isr, const uint8_t* req, uint16_t req_len,
143 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
144 ErrorCode HandleExecuteCommands(bool in_isr, const uint8_t* req, uint16_t req_len,
145 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
146
147 ErrorCode BuildInfoStringResponse(uint8_t cmd, const char* str, uint8_t* resp,
148 uint16_t resp_cap, uint16_t& out_len);
149 ErrorCode BuildInfoU8Response(uint8_t cmd, uint8_t val, uint8_t* resp,
150 uint16_t resp_cap, uint16_t& out_len);
151 ErrorCode BuildInfoU16Response(uint8_t cmd, uint16_t val, uint8_t* resp,
152 uint16_t resp_cap, uint16_t& out_len);
153 ErrorCode BuildInfoU32Response(uint8_t cmd, uint32_t val, uint8_t* resp,
154 uint16_t resp_cap, uint16_t& out_len);
155
156 uint8_t MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack) const;
157 uint8_t MapAckToDapResp(LibXR::Debug::JtagProtocol::Ack ack) const;
158 ErrorCode HandleJtagTransfer(bool in_isr, const uint8_t* req, uint16_t req_len,
159 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
160 ErrorCode HandleJtagTransferBlock(bool in_isr, const uint8_t* req, uint16_t req_len,
161 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
162 ErrorCode HandleJtagWriteAbort(bool in_isr, const uint8_t* req, uint16_t req_len,
163 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
164 void SetTransferAbortFlag(bool on);
165
166 void DriveReset(bool release);
167 void DelayUsIfAllowed(bool in_isr, uint32_t us);
168
169 private:
170 template <typename E>
171 static constexpr uint8_t to_u8(E e)
172 {
173 return static_cast<uint8_t>(e);
174 }
175
176 static constexpr uint8_t DAP_OK = 0x00u;
177 static constexpr uint8_t DAP_ERROR = 0xFFu;
178
179 static inline ErrorCode build_unknown_cmd_response(uint8_t* resp, uint16_t cap,
180 uint16_t& out_len)
181 {
182 if (!resp || cap < 1u)
183 {
184 out_len = 0u;
186 }
187 resp[0] = 0xFFu;
188 out_len = 1u;
189 return ErrorCode::OK;
190 }
191
192 static inline ErrorCode build_cmd_status_response(uint8_t cmd, uint8_t status,
193 uint8_t* resp, uint16_t cap,
194 uint16_t& out_len)
195 {
196 if (!resp || cap < 2u)
197 {
198 out_len = 0u;
200 }
201 resp[0] = cmd;
202 resp[1] = status;
203 out_len = 2u;
204 return ErrorCode::OK;
205 }
206
207 static constexpr uint16_t MAX_REQ = DapLinkV1Def::MAX_REQUEST_SIZE;
208 static constexpr uint16_t MAX_RESP = DapLinkV1Def::MAX_RESPONSE_SIZE;
209 static constexpr uint8_t JTAG_MAX_DEVICES = 16u;
210
211 SwdPort& swd_;
212 LibXR::Debug::Jtag* jtag_ = nullptr;
214 uint8_t jtag_ir_len_[JTAG_MAX_DEVICES] = {};
215 LibXR::GPIO* nreset_gpio_ = nullptr;
216
217 uint8_t swj_shadow_ = static_cast<uint8_t>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
218 DapLinkV1Def::DAP_SWJ_NRESET);
219 bool last_nreset_level_high_ = true;
220
222 InfoStrings info_{"XRobot", "DAPLinkV1", "00000001", "1.0.0", "XRUSB",
223 "XRDAP", "XRobot", "DAP_DEMO", "0.1.0"};
224
225 uint32_t swj_clock_hz_ = 1000000u;
226 uint32_t match_mask_ = 0xFFFFFFFFu;
227
228 Endpoint* ep_in_ = nullptr; // Cached HID IN endpoint
229 Endpoint* ep_out_ = nullptr; // Cached HID OUT endpoint
230
232 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataOutCompleteStatic, this);
234 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataInCompleteStatic, this);
235
236 bool inited_ = false;
237};
238
239template <typename SwdPort>
240DapLinkV1Class<SwdPort>::DapLinkV1Class(Endpoint::EPNumber in_ep_num,
241 Endpoint::EPNumber out_ep_num, SwdPort& swd_link,
242 LibXR::GPIO* nreset_gpio)
243 : HID(in_ep_num, out_ep_num, true, 1, 1, DEFAULT_INTERFACE_STRING),
244 swd_(swd_link),
245 nreset_gpio_(nreset_gpio)
246{
247 if constexpr (JTAG_ENABLED)
248 {
249 jtag_chain_.ir_length = jtag_ir_len_;
250 jtag_chain_.count = 0u;
251 jtag_chain_.index = 0u;
252 }
253 (void)swd_.SetClockHz(swj_clock_hz_);
254}
255
256template <typename SwdPort>
257void DapLinkV1Class<SwdPort>::SetInfoStrings(const InfoStrings& info)
258{
259 info_ = info;
260}
261
262template <typename SwdPort>
263void DapLinkV1Class<SwdPort>::SetJtag(LibXR::Debug::Jtag* jtag)
264{
265 if constexpr (JTAG_ENABLED)
266 {
267 jtag_ = jtag;
268 }
269 else
270 {
271 (void)jtag;
272 }
273}
274
275template <typename SwdPort>
276const LibXR::USB::DapLinkV1Def::State& DapLinkV1Class<SwdPort>::GetState() const
277{
278 return dap_state_;
279}
280
281template <typename SwdPort>
282bool DapLinkV1Class<SwdPort>::IsInited() const
283{
284 return inited_;
285}
286
287template <typename SwdPort>
295
296template <typename SwdPort>
298{
299 return ConstRawData{DAPLINK_V1_REPORT_DESC, sizeof(DAPLINK_V1_REPORT_DESC)};
300}
301
302template <typename SwdPort>
304 uint8_t start_itf_num, bool in_isr)
305{
306 HID::BindEndpoints(endpoint_pool, start_itf_num, in_isr);
307
308 ep_in_ = GetInEndpoint();
309 ep_out_ = GetOutEndpoint();
310
311 if (ep_in_ != nullptr)
312 {
313 // Double buffer splits RawData into two halves; ensure EP IN buffer >= 2 * MAX_RESP.
314 ep_in_->Configure(
316 ep_in_->SetOnTransferCompleteCallback(on_data_in_cb_);
317 }
318
319 if (ep_out_ != nullptr)
320 {
321 // Double buffer splits RawData into two halves; ensure EP OUT buffer >= 2 * MAX_REQ.
322 ep_out_->Configure(
324 ep_out_->SetOnTransferCompleteCallback(on_data_out_cb_);
325 }
326
327 inited_ = true;
328 match_mask_ = 0xFFFFFFFFu;
329
330 dap_state_ = {};
331 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
332 dap_state_.transfer_abort = false;
333
334 swj_clock_hz_ = 1000000u;
335 (void)swd_.SetClockHz(swj_clock_hz_);
336 if constexpr (JTAG_ENABLED)
337 {
338 if (jtag_ != nullptr)
339 {
340 (void)jtag_->SetClockHz(swj_clock_hz_);
341 }
342 }
343
344 if constexpr (JTAG_ENABLED)
345 {
346 jtag_chain_.count = 0u;
347 jtag_chain_.index = 0u;
348 jtag_chain_.ir_before_bits_len = 0u;
349 jtag_chain_.ir_after_bits_len = 0u;
350 jtag_chain_.dr_before_bits_len = 0u;
351 jtag_chain_.dr_after_bits_len = 0u;
352 Memory::FastSet(jtag_ir_len_, 0, sizeof(jtag_ir_len_));
353 }
354
355 last_nreset_level_high_ = true;
356 swj_shadow_ = static_cast<uint8_t>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
357 DapLinkV1Def::DAP_SWJ_NRESET);
358
359 ArmOutTransferIfIdle();
360}
361
362template <typename SwdPort>
364{
365 inited_ = false;
366
367 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
368 dap_state_.transfer_abort = false;
369
370 HID::UnbindEndpoints(endpoint_pool, in_isr);
371
372 ep_in_ = nullptr;
373 ep_out_ = nullptr;
374
375 swd_.Close();
376 if constexpr (JTAG_ENABLED)
377 {
378 if (jtag_ != nullptr)
379 {
380 jtag_->Close();
381 }
382 }
383
384 last_nreset_level_high_ = true;
385 swj_shadow_ = static_cast<uint8_t>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
386 DapLinkV1Def::DAP_SWJ_NRESET);
387}
388
389template <typename SwdPort>
392{
393 if (self && self->inited_)
394 {
395 self->OnDataOutComplete(in_isr, data);
396 }
397}
398
399template <typename SwdPort>
400void DapLinkV1Class<SwdPort>::OnDataInCompleteStatic(bool in_isr, DapLinkV1Class* self,
402{
403 if (self && self->inited_)
404 {
405 self->OnDataInComplete(in_isr, data);
406 }
407}
408
409template <typename SwdPort>
410void DapLinkV1Class<SwdPort>::OnDataOutComplete(bool in_isr, LibXR::ConstRawData& data)
411{
412 if (!inited_ || !ep_in_ || !ep_out_)
413 {
414 return;
415 }
416
417 const auto* REQ = static_cast<const uint8_t*>(data.addr_);
418 const uint16_t REQ_LEN = static_cast<uint16_t>(data.size_);
419
420 auto tx_buff = ep_in_->GetBuffer();
421 const uint16_t RESP_CAP = static_cast<uint16_t>(tx_buff.size_);
422 const uint16_t TX_LEN = (RESP_CAP < MAX_RESP) ? RESP_CAP : MAX_RESP;
423
424 if (ep_in_->GetState() == Endpoint::State::IDLE)
425 {
426 ArmOutTransferIfIdle();
427 }
428
429 Memory::FastSet(tx_buff.addr_, 0, RESP_CAP);
430 uint16_t out_len = 0u;
431 auto ans = ProcessOneCommand(
432 in_isr, REQ, REQ_LEN, reinterpret_cast<uint8_t*>(tx_buff.addr_), RESP_CAP, out_len);
433 UNUSED(ans);
434 UNUSED(out_len);
435
436 if (ep_in_->GetState() == Endpoint::State::IDLE)
437 {
438 ep_in_->Transfer(TX_LEN);
439 ep_in_->SetActiveLength(0);
440 }
441 else
442 {
443 ep_in_->SetActiveLength(TX_LEN);
444 }
445}
446
447template <typename SwdPort>
448void DapLinkV1Class<SwdPort>::OnDataInComplete(bool in_isr, LibXR::ConstRawData& data)
449{
450 UNUSED(in_isr);
451 UNUSED(data);
452
453 auto act_len = ep_in_->GetActiveLength();
454 if (act_len > 0)
455 {
456 ep_in_->Transfer(act_len);
457 ep_in_->SetActiveLength(0);
458 }
459
460 ArmOutTransferIfIdle();
461}
462
463template <typename SwdPort>
464void DapLinkV1Class<SwdPort>::ArmOutTransferIfIdle()
465{
466 if (!inited_ || !ep_out_)
467 {
468 return;
469 }
470
471 if (ep_out_->GetState() != Endpoint::State::IDLE)
472 {
473 return;
474 }
475
476 (void)ep_out_->Transfer(ep_out_->MaxTransferSize());
477}
478
479template <typename SwdPort>
480ErrorCode DapLinkV1Class<SwdPort>::ProcessOneCommand(bool in_isr, const uint8_t* req,
481 uint16_t req_len, uint8_t* resp,
482 uint16_t resp_cap, uint16_t& out_len)
483{
484 out_len = 0u;
485
486 if (!req || !resp || req_len < 1u || resp_cap < 1u)
487 {
488 if (resp && resp_cap >= 1u)
489 {
490 BuildNotSupportResponse(resp, resp_cap, out_len);
491 }
492 return ErrorCode::ARG_ERR;
493 }
494
495 const uint8_t CMD = req[0];
496
497 switch (CMD)
498 {
499 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::INFO):
500 return HandleInfo(in_isr, req, req_len, resp, resp_cap, out_len);
501 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS):
502 return HandleHostStatus(in_isr, req, req_len, resp, resp_cap, out_len);
503 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT):
504 return HandleConnect(in_isr, req, req_len, resp, resp_cap, out_len);
505 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT):
506 return HandleDisconnect(in_isr, req, req_len, resp, resp_cap, out_len);
507 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE):
508 return HandleTransferConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
509 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER):
510 return HandleTransfer(in_isr, req, req_len, resp, resp_cap, out_len);
511 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK):
512 return HandleTransferBlock(in_isr, req, req_len, resp, resp_cap, out_len);
513 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT):
514 return HandleTransferAbort(in_isr, req, req_len, resp, resp_cap, out_len);
515 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT):
516 return HandleWriteABORT(in_isr, req, req_len, resp, resp_cap, out_len);
517 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::DELAY):
518 return HandleDelay(in_isr, req, req_len, resp, resp_cap, out_len);
519 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET):
520 return HandleResetTarget(in_isr, req, req_len, resp, resp_cap, out_len);
521 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS):
522 return HandleSWJPins(in_isr, req, req_len, resp, resp_cap, out_len);
523 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK):
524 return HandleSWJClock(in_isr, req, req_len, resp, resp_cap, out_len);
525 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE):
526 return HandleSWJSequence(in_isr, req, req_len, resp, resp_cap, out_len);
527 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE):
528 return HandleSWDConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
529 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE):
530 return HandleSWDSequence(in_isr, req, req_len, resp, resp_cap, out_len);
531 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_SEQUENCE):
532 if constexpr (JTAG_ENABLED)
533 {
534 return HandleJTAGSequence(in_isr, req, req_len, resp, resp_cap, out_len);
535 }
536 BuildNotSupportResponse(resp, resp_cap, out_len);
538 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_CONFIGURE):
539 if constexpr (JTAG_ENABLED)
540 {
541 return HandleJTAGConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
542 }
543 BuildNotSupportResponse(resp, resp_cap, out_len);
545 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_IDCODE):
546 if constexpr (JTAG_ENABLED)
547 {
548 return HandleJTAGIdCode(in_isr, req, req_len, resp, resp_cap, out_len);
549 }
550 BuildNotSupportResponse(resp, resp_cap, out_len);
552 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::QUEUE_COMMANDS):
553 return HandleQueueCommands(in_isr, req, req_len, resp, resp_cap, out_len);
554 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::EXECUTE_COMMANDS):
555 return HandleExecuteCommands(in_isr, req, req_len, resp, resp_cap, out_len);
556 default:
557 (void)build_unknown_cmd_response(resp, resp_cap, out_len);
559 }
560}
561
562template <typename SwdPort>
563void DapLinkV1Class<SwdPort>::BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap,
564 uint16_t& out_len)
565{
566 if (!resp || resp_cap < 1u)
567 {
568 out_len = 0u;
569 return;
570 }
571 resp[0] = 0xFFu;
572 out_len = 1u;
573}
574
575template <typename SwdPort>
576ErrorCode DapLinkV1Class<SwdPort>::HandleInfo(bool /*in_isr*/, const uint8_t* req,
577 uint16_t req_len, uint8_t* resp,
578 uint16_t resp_cap, uint16_t& out_len)
579{
580 if (req_len < 2u)
581 {
582 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
583 resp[1] = 0u;
584 out_len = 2u;
585 return ErrorCode::ARG_ERR;
586 }
587
588 const uint8_t INFO_ID = req[1];
589
590 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
591
592 switch (INFO_ID)
593 {
594 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::VENDOR):
595 return BuildInfoStringResponse(resp[0], info_.vendor, resp, resp_cap, out_len);
596 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT):
597 return BuildInfoStringResponse(resp[0], info_.product, resp, resp_cap, out_len);
598 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::SERIAL_NUMBER):
599 return BuildInfoStringResponse(resp[0], info_.serial, resp, resp_cap, out_len);
600 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::FIRMWARE_VERSION):
601 return BuildInfoStringResponse(resp[0], info_.firmware_ver, resp, resp_cap,
602 out_len);
603 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_VENDOR):
604 return BuildInfoStringResponse(resp[0], info_.device_vendor, resp, resp_cap,
605 out_len);
606 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_NAME):
607 return BuildInfoStringResponse(resp[0], info_.device_name, resp, resp_cap, out_len);
608 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_VENDOR):
609 return BuildInfoStringResponse(resp[0], info_.board_vendor, resp, resp_cap,
610 out_len);
611 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_NAME):
612 return BuildInfoStringResponse(resp[0], info_.board_name, resp, resp_cap, out_len);
613 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT_FIRMWARE_VERSION):
614 return BuildInfoStringResponse(resp[0], info_.product_fw_ver, resp, resp_cap,
615 out_len);
616 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::CAPABILITIES):
617 {
619 if constexpr (JTAG_ENABLED)
620 {
621 if (jtag_ != nullptr)
622 {
623 caps = static_cast<uint8_t>(caps | LibXR::USB::DapLinkV1Def::DAP_CAP_JTAG);
624 }
625 }
626 return BuildInfoU8Response(resp[0], caps, resp, resp_cap, out_len);
627 }
628 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_COUNT):
629 return BuildInfoU8Response(resp[0], 1, resp, resp_cap, out_len);
630 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_SIZE):
631 return BuildInfoU16Response(resp[0], MAX_RESP, resp, resp_cap, out_len);
632 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::TIMESTAMP_CLOCK):
633 return BuildInfoU32Response(resp[0], 1000000U, resp, resp_cap, out_len);
634 default:
635 resp[1] = 0u;
636 out_len = 2u;
637 return ErrorCode::OK;
638 }
639}
640
641template <typename SwdPort>
642ErrorCode DapLinkV1Class<SwdPort>::BuildInfoStringResponse(uint8_t cmd, const char* str,
643 uint8_t* resp,
644 uint16_t resp_cap,
645 uint16_t& out_len)
646{
647 resp[0] = cmd;
648 resp[1] = 0u;
649
650 if (!str)
651 {
652 out_len = 2u;
653 return ErrorCode::OK;
654 }
655
656 const size_t N_WITH_NUL = std::strlen(str) + 1;
657 const size_t MAX_PAYLOAD = (resp_cap >= 2u) ? (resp_cap - 2u) : 0u;
658 if (MAX_PAYLOAD == 0u)
659 {
660 out_len = 2u;
661 return ErrorCode::OK;
662 }
663
664 const size_t COPY_N = (N_WITH_NUL > MAX_PAYLOAD) ? MAX_PAYLOAD : N_WITH_NUL;
665 Memory::FastCopy(&resp[2], str, COPY_N);
666 resp[1] = static_cast<uint8_t>(COPY_N);
667 out_len = static_cast<uint16_t>(COPY_N + 2u);
668 return ErrorCode::OK;
669}
670
671template <typename SwdPort>
672ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU8Response(uint8_t cmd, uint8_t val,
673 uint8_t* resp, uint16_t resp_cap,
674 uint16_t& out_len)
675{
676 if (resp_cap < 3u)
677 {
678 out_len = 0u;
680 }
681 resp[0] = cmd;
682 resp[1] = 1u;
683 resp[2] = val;
684 out_len = 3u;
685 return ErrorCode::OK;
686}
687
688template <typename SwdPort>
689ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU16Response(uint8_t cmd, uint16_t val,
690 uint8_t* resp, uint16_t resp_cap,
691 uint16_t& out_len)
692{
693 if (resp_cap < 4u)
694 {
695 out_len = 0u;
697 }
698 resp[0] = cmd;
699 resp[1] = 2u;
700 Memory::FastCopy(&resp[2], &val, sizeof(val));
701 out_len = 4u;
702 return ErrorCode::OK;
703}
704
705template <typename SwdPort>
706ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU32Response(uint8_t cmd, uint32_t val,
707 uint8_t* resp, uint16_t resp_cap,
708 uint16_t& out_len)
709{
710 if (resp_cap < 6u)
711 {
712 out_len = 0u;
714 }
715 resp[0] = cmd;
716 resp[1] = 4u;
717 Memory::FastCopy(&resp[2], &val, sizeof(val));
718 out_len = 6u;
719 return ErrorCode::OK;
720}
721
722template <typename SwdPort>
723ErrorCode DapLinkV1Class<SwdPort>::HandleHostStatus(bool /*in_isr*/,
724 const uint8_t* /*req*/,
725 uint16_t /*req_len*/, uint8_t* resp,
726 uint16_t resp_cap, uint16_t& out_len)
727{
728 if (resp_cap < 2u)
729 {
730 out_len = 0u;
732 }
733 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS);
734 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
735 out_len = 2u;
736 return ErrorCode::OK;
737}
738
739template <typename SwdPort>
740ErrorCode DapLinkV1Class<SwdPort>::HandleConnect(bool /*in_isr*/, const uint8_t* req,
741 uint16_t req_len, uint8_t* resp,
742 uint16_t resp_cap, uint16_t& out_len)
743{
744 if (resp_cap < 2u)
745 {
746 out_len = 0u;
748 }
749
750 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT);
751
752 uint8_t port = 0u;
753 if (req_len >= 2u)
754 {
755 port = req[1];
756 }
757
758 if (port == 0u)
759 {
760 port = to_u8(LibXR::USB::DapLinkV1Def::Port::SWD);
761 }
762
763 if (port == to_u8(LibXR::USB::DapLinkV1Def::Port::SWD))
764 {
765 (void)swd_.EnterSwd();
766 (void)swd_.SetClockHz(swj_clock_hz_);
767
768 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::SWD;
769 dap_state_.transfer_abort = false;
770
771 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::SWD);
772 }
773 else if (port == to_u8(LibXR::USB::DapLinkV1Def::Port::JTAG))
774 {
775 if constexpr (!JTAG_ENABLED)
776 {
777 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
778 }
779 else
780 {
781 if (jtag_ == nullptr)
782 {
783 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
784 }
785 else
786 {
787 (void)jtag_->SetClockHz(swj_clock_hz_);
788 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::JTAG;
789 dap_state_.transfer_abort = false;
790 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::JTAG);
791 }
792 }
793 }
794 else
795 {
796 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
797 }
798
799 out_len = 2u;
800 return ErrorCode::OK;
801}
802
803template <typename SwdPort>
804ErrorCode DapLinkV1Class<SwdPort>::HandleDisconnect(bool /*in_isr*/,
805 const uint8_t* /*req*/,
806 uint16_t /*req_len*/, uint8_t* resp,
807 uint16_t resp_cap, uint16_t& out_len)
808{
809 if (resp_cap < 2u)
810 {
811 out_len = 0u;
813 }
814
815 swd_.Close();
816 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
817 dap_state_.transfer_abort = false;
818
819 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT);
820 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
821 out_len = 2u;
822 return ErrorCode::OK;
823}
824
825template <typename SwdPort>
826ErrorCode DapLinkV1Class<SwdPort>::HandleTransferConfigure(
827 bool /*in_isr*/, const uint8_t* req, uint16_t req_len, uint8_t* resp,
828 uint16_t resp_cap, uint16_t& out_len)
829{
830 if (resp_cap < 2u)
831 {
832 out_len = 0u;
834 }
835
836 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE);
837
838 if (req_len < 6u)
839 {
840 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
841 out_len = 2u;
842 return ErrorCode::ARG_ERR;
843 }
844
845 const uint8_t IDLE = req[1];
846
847 uint16_t wait_retry = 0u;
848 uint16_t match_retry = 0u;
849 Memory::FastCopy(&wait_retry, &req[2], sizeof(wait_retry));
850 Memory::FastCopy(&match_retry, &req[4], sizeof(match_retry));
851
852 dap_state_.transfer_cfg.idle_cycles = IDLE;
853 dap_state_.transfer_cfg.retry_count = wait_retry;
854 dap_state_.transfer_cfg.match_retry = match_retry;
855
856 LibXR::Debug::Swd::TransferPolicy pol = swd_.GetTransferPolicy();
857 pol.idle_cycles = IDLE;
858 pol.wait_retry = wait_retry;
859 swd_.SetTransferPolicy(pol);
860
861 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
862 out_len = 2u;
863 return ErrorCode::OK;
864}
865
866template <typename SwdPort>
867ErrorCode DapLinkV1Class<SwdPort>::HandleTransferAbort(bool /*in_isr*/,
868 const uint8_t* /*req*/,
869 uint16_t /*req_len*/,
870 uint8_t* resp, uint16_t resp_cap,
871 uint16_t& out_len)
872{
873 if (resp_cap < 2u)
874 {
875 out_len = 0u;
877 }
878
879 SetTransferAbortFlag(true);
880
881 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT);
882 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
883 out_len = 2u;
884 return ErrorCode::OK;
885}
886
887template <typename SwdPort>
888ErrorCode DapLinkV1Class<SwdPort>::HandleWriteABORT(bool /*in_isr*/, const uint8_t* req,
889 uint16_t req_len, uint8_t* resp,
890 uint16_t resp_cap, uint16_t& out_len)
891{
892 if (resp_cap < 2u)
893 {
894 out_len = 0u;
896 }
897
898 if constexpr (JTAG_ENABLED)
899 {
900 if (dap_state_.debug_port == LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
901 {
902 return HandleJtagWriteAbort(false, req, req_len, resp, resp_cap, out_len);
903 }
904 }
905
906 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT);
907
908 if (req_len < 6u)
909 {
910 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
911 out_len = 2u;
912 return ErrorCode::ARG_ERR;
913 }
914
915 uint32_t flags = 0u;
916 Memory::FastCopy(&flags, &req[2], sizeof(flags));
917
918 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
919 const ErrorCode EC = swd_.WriteAbortTxn(flags, ack);
920 resp[1] = (EC == ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
921 ? to_u8(LibXR::USB::DapLinkV1Def::Status::OK)
922 : to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
923
924 out_len = 2u;
925 return ErrorCode::OK;
926}
927
928template <typename SwdPort>
929ErrorCode DapLinkV1Class<SwdPort>::HandleDelay(bool /*in_isr*/, const uint8_t* req,
930 uint16_t req_len, uint8_t* resp,
931 uint16_t resp_cap, uint16_t& out_len)
932{
933 if (resp_cap < 2u)
934 {
935 out_len = 0u;
937 }
938
939 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::DELAY);
940
941 if (req_len < 3u)
942 {
943 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
944 out_len = 2u;
945 return ErrorCode::ARG_ERR;
946 }
947
948 uint16_t us = 0u;
949 Memory::FastCopy(&us, &req[1], sizeof(us));
950
952
953 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
954 out_len = 2u;
955 return ErrorCode::OK;
956}
957
958template <typename SwdPort>
959ErrorCode DapLinkV1Class<SwdPort>::HandleResetTarget(bool in_isr, const uint8_t* /*req*/,
960 uint16_t /*req_len*/, uint8_t* resp,
961 uint16_t resp_cap, uint16_t& out_len)
962{
963 if (!resp || resp_cap < 3u)
964 {
965 out_len = 0u;
967 }
968
969 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET);
970
971 uint8_t execute = 0u;
972 if (nreset_gpio_ != nullptr)
973 {
974 DriveReset(false);
975 DelayUsIfAllowed(in_isr, 1000u);
976 DriveReset(true);
977 DelayUsIfAllowed(in_isr, 1000u);
978 execute = 1u;
979 }
980
981 resp[1] = DAP_OK;
982 resp[2] = execute;
983 out_len = 3u;
984 return ErrorCode::OK;
985}
986
987template <typename SwdPort>
988ErrorCode DapLinkV1Class<SwdPort>::HandleSWJPins(bool /*in_isr*/, const uint8_t* req,
989 uint16_t req_len, uint8_t* resp,
990 uint16_t resp_cap, uint16_t& out_len)
991{
992 if (!resp || resp_cap < 2u)
993 {
994 out_len = 0u;
996 }
997
998 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS);
999
1000 if (!req || req_len < 7u)
1001 {
1002 resp[1] = 0u;
1003 out_len = 2u;
1004 return ErrorCode::ARG_ERR;
1005 }
1006
1007 const uint8_t PIN_OUT = req[1];
1008 const uint8_t PIN_SEL = req[2];
1009
1010 uint32_t wait_us = 0u;
1011 Memory::FastCopy(&wait_us, &req[3], sizeof(wait_us));
1012
1013 swj_shadow_ = static_cast<uint8_t>((swj_shadow_ & static_cast<uint8_t>(~PIN_SEL)) |
1014 (PIN_OUT & PIN_SEL));
1015
1016 if ((PIN_SEL & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u)
1017 {
1018 const bool LEVEL_HIGH = ((PIN_OUT & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u);
1019 DriveReset(LEVEL_HIGH);
1020 }
1021
1022 auto read_pins = [&]() -> uint8_t
1023 {
1024 uint8_t pin_in = swj_shadow_;
1025
1026 if (nreset_gpio_ != nullptr)
1027 {
1028 if (nreset_gpio_->Read())
1029 {
1030 pin_in |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
1031 }
1032 else
1033 {
1034 pin_in = static_cast<uint8_t>(
1035 pin_in & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
1036 }
1037 }
1038
1039 return pin_in;
1040 };
1041
1042 uint8_t pin_in = 0u;
1043 if (wait_us == 0u || PIN_SEL == 0u)
1044 {
1045 pin_in = read_pins();
1046 }
1047 else
1048 {
1049 const uint64_t START = LibXR::Timebase::GetMicroseconds();
1050 const uint8_t EXPECT = static_cast<uint8_t>(PIN_OUT & PIN_SEL);
1051
1052 do
1053 {
1054 pin_in = read_pins();
1055 if ((pin_in & PIN_SEL) == EXPECT)
1056 {
1057 break;
1058 }
1059 } while ((static_cast<uint64_t>(LibXR::Timebase::GetMicroseconds()) - START) <
1060 wait_us);
1061 }
1062
1063 resp[1] = pin_in;
1064 out_len = 2u;
1065 return ErrorCode::OK;
1066}
1067
1068template <typename SwdPort>
1069ErrorCode DapLinkV1Class<SwdPort>::HandleSWJClock(bool /*in_isr*/, const uint8_t* req,
1070 uint16_t req_len, uint8_t* resp,
1071 uint16_t resp_cap, uint16_t& out_len)
1072{
1073 if (resp_cap < 2u)
1074 {
1075 out_len = 0u;
1076 return ErrorCode::NOT_FOUND;
1077 }
1078
1079 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK);
1080
1081 if (req_len < 5u)
1082 {
1083 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1084 out_len = 2u;
1085 return ErrorCode::ARG_ERR;
1086 }
1087
1088 uint32_t hz = 0u;
1089 Memory::FastCopy(&hz, &req[1], sizeof(hz));
1090
1091 swj_clock_hz_ = hz;
1092 (void)swd_.SetClockHz(hz);
1093 if constexpr (JTAG_ENABLED)
1094 {
1095 if (jtag_ != nullptr)
1096 {
1097 (void)jtag_->SetClockHz(hz);
1098 }
1099 }
1100
1101 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
1102 out_len = 2u;
1103 return ErrorCode::OK;
1104}
1105
1106template <typename SwdPort>
1107ErrorCode DapLinkV1Class<SwdPort>::HandleSWJSequence(bool /*in_isr*/, const uint8_t* req,
1108 uint16_t req_len, uint8_t* resp,
1109 uint16_t resp_cap, uint16_t& out_len)
1110{
1111 if (!resp || resp_cap < 2u)
1112 {
1113 out_len = 0u;
1114 return ErrorCode::NOT_FOUND;
1115 }
1116
1117 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE);
1118 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
1119 out_len = 2u;
1120
1121 if (!req || req_len < 2u)
1122 {
1123 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1124 return ErrorCode::ARG_ERR;
1125 }
1126
1127 uint32_t bit_count = req[1];
1128 if (bit_count == 0u)
1129 {
1130 bit_count = 256u;
1131 }
1132
1133 const uint32_t BYTE_COUNT = (bit_count + 7u) / 8u;
1134 if (req_len < (2u + BYTE_COUNT))
1135 {
1136 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1137 return ErrorCode::ARG_ERR;
1138 }
1139
1140 const uint8_t* DATA = &req[2];
1141 const ErrorCode EC = swd_.SeqWriteBits(bit_count, DATA);
1142 if (EC != ErrorCode::OK)
1143 {
1144 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1145 return ErrorCode::OK;
1146 }
1147
1148 swj_shadow_ = static_cast<uint8_t>(
1149 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWCLK_TCK));
1150
1151 bool last_swdio = false;
1152 if (bit_count != 0u)
1153 {
1154 const uint32_t LAST_I = bit_count - 1u;
1155 last_swdio = (((DATA[LAST_I / 8u] >> (LAST_I & 7u)) & 0x01u) != 0u);
1156 }
1157
1158 if (last_swdio)
1159 {
1160 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS;
1161 }
1162 else
1163 {
1164 swj_shadow_ = static_cast<uint8_t>(
1165 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS));
1166 }
1167
1168 return ErrorCode::OK;
1169}
1170
1171template <typename SwdPort>
1172ErrorCode DapLinkV1Class<SwdPort>::HandleSWDConfigure(bool /*in_isr*/,
1173 const uint8_t* /*req*/,
1174 uint16_t /*req_len*/, uint8_t* resp,
1175 uint16_t resp_cap,
1176 uint16_t& out_len)
1177{
1178 if (resp_cap < 2u)
1179 {
1180 out_len = 0u;
1181 return ErrorCode::NOT_FOUND;
1182 }
1183
1184 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE);
1185 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
1186 out_len = 2u;
1187 return ErrorCode::OK;
1188}
1189
1190template <typename SwdPort>
1191ErrorCode DapLinkV1Class<SwdPort>::HandleSWDSequence(bool /*in_isr*/, const uint8_t* req,
1192 uint16_t req_len, uint8_t* resp,
1193 uint16_t resp_cap, uint16_t& out_len)
1194{
1195 if (!req || !resp || resp_cap < 2u)
1196 {
1197 out_len = 0u;
1198 return ErrorCode::ARG_ERR;
1199 }
1200
1201 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE);
1202 resp[1] = DAP_OK;
1203 out_len = 2u;
1204
1205 if (req_len < 2u)
1206 {
1207 resp[1] = DAP_ERROR;
1208 out_len = 2u;
1209 return ErrorCode::ARG_ERR;
1210 }
1211
1212 const uint8_t SEQ_CNT = req[1];
1213 uint16_t req_off = 2u;
1214 uint16_t resp_off = 2u;
1215
1216 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1217 {
1218 if (req_off >= req_len)
1219 {
1220 resp[1] = DAP_ERROR;
1221 out_len = 2u;
1222 return ErrorCode::ARG_ERR;
1223 }
1224
1225 const uint8_t INFO = req[req_off++];
1226 uint32_t cycles = static_cast<uint32_t>(INFO & 0x3Fu);
1227 if (cycles == 0u)
1228 {
1229 cycles = 64u;
1230 }
1231
1232 const bool MODE_IN = ((INFO & 0x80u) != 0u);
1233 const uint16_t BYTES = static_cast<uint16_t>((cycles + 7u) / 8u);
1234
1235 if (!MODE_IN)
1236 {
1237 if (req_off + BYTES > req_len)
1238 {
1239 resp[1] = DAP_ERROR;
1240 out_len = 2u;
1241 return ErrorCode::ARG_ERR;
1242 }
1243
1244 const uint8_t* DATA = &req[req_off];
1245 req_off = static_cast<uint16_t>(req_off + BYTES);
1246
1247 const ErrorCode EC = swd_.SeqWriteBits(cycles, DATA);
1248 if (EC != ErrorCode::OK)
1249 {
1250 resp[1] = DAP_ERROR;
1251 out_len = 2u;
1252 return ErrorCode::OK;
1253 }
1254 }
1255 else
1256 {
1257 if (resp_off + BYTES > resp_cap)
1258 {
1259 resp[1] = DAP_ERROR;
1260 out_len = 2u;
1261 return ErrorCode::NOT_FOUND;
1262 }
1263
1264 Memory::FastSet(&resp[resp_off], 0, BYTES);
1265 const ErrorCode EC = swd_.SeqReadBits(cycles, &resp[resp_off]);
1266 if (EC != ErrorCode::OK)
1267 {
1268 resp[1] = DAP_ERROR;
1269 out_len = 2u;
1270 return ErrorCode::OK;
1271 }
1272
1273 resp_off = static_cast<uint16_t>(resp_off + BYTES);
1274 }
1275 }
1276
1277 out_len = resp_off;
1278 return ErrorCode::OK;
1279}
1280
1281template <typename SwdPort>
1282ErrorCode DapLinkV1Class<SwdPort>::HandleJTAGSequence(bool /*in_isr*/, const uint8_t* req,
1283 uint16_t req_len, uint8_t* resp,
1284 uint16_t resp_cap,
1285 uint16_t& out_len)
1286{
1287 if (!req || !resp || resp_cap < 2u)
1288 {
1289 out_len = 0u;
1290 return ErrorCode::ARG_ERR;
1291 }
1292
1293 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_SEQUENCE);
1294 resp[1] = DAP_OK;
1295 out_len = 2u;
1296
1297 if (jtag_ == nullptr)
1298 {
1299 resp[1] = DAP_ERROR;
1300 return ErrorCode::OK;
1301 }
1302
1303 if (req_len < 2u)
1304 {
1305 resp[1] = DAP_ERROR;
1306 return ErrorCode::ARG_ERR;
1307 }
1308
1309 const uint8_t SEQ_CNT = req[1];
1310 uint16_t req_off = 2u;
1311 uint16_t resp_off = 2u;
1312
1313 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1314 {
1315 if (req_off >= req_len)
1316 {
1317 resp[1] = DAP_ERROR;
1318 out_len = 2u;
1319 return ErrorCode::ARG_ERR;
1320 }
1321
1322 const uint8_t INFO = req[req_off++];
1323 uint32_t cycles = static_cast<uint32_t>(INFO & 0x3Fu);
1324 if (cycles == 0u)
1325 {
1326 cycles = 64u;
1327 }
1328
1329 const bool TMS = ((INFO & LibXR::Debug::JtagProtocol::JTAG_SEQUENCE_TMS) != 0u);
1330 const bool CAPTURE = ((INFO & LibXR::Debug::JtagProtocol::JTAG_SEQUENCE_TDO) != 0u);
1331 const uint16_t BYTES = static_cast<uint16_t>((cycles + 7u) / 8u);
1332
1333 if (req_off + BYTES > req_len)
1334 {
1335 resp[1] = DAP_ERROR;
1336 out_len = 2u;
1337 return ErrorCode::ARG_ERR;
1338 }
1339
1340 if (CAPTURE && (resp_off + BYTES > resp_cap))
1341 {
1342 resp[1] = DAP_ERROR;
1343 out_len = 2u;
1344 return ErrorCode::NOT_FOUND;
1345 }
1346
1347 const uint8_t* DATA = &req[req_off];
1348 uint8_t* OUT = CAPTURE ? &resp[resp_off] : nullptr;
1349 if (CAPTURE)
1350 {
1351 Memory::FastSet(OUT, 0, BYTES);
1352 }
1353
1354 const ErrorCode EC = jtag_->Sequence(cycles, TMS, DATA, OUT);
1355 if (EC != ErrorCode::OK)
1356 {
1357 resp[1] = DAP_ERROR;
1358 out_len = 2u;
1359 return ErrorCode::OK;
1360 }
1361
1362 req_off = static_cast<uint16_t>(req_off + BYTES);
1363 if (CAPTURE)
1364 {
1365 resp_off = static_cast<uint16_t>(resp_off + BYTES);
1366 }
1367 }
1368
1369 out_len = resp_off;
1370 return ErrorCode::OK;
1371}
1372
1373template <typename SwdPort>
1374ErrorCode DapLinkV1Class<SwdPort>::HandleJTAGConfigure(bool /*in_isr*/,
1375 const uint8_t* req,
1376 uint16_t req_len, uint8_t* resp,
1377 uint16_t resp_cap,
1378 uint16_t& out_len)
1379{
1380 if (!req || !resp || resp_cap < 2u)
1381 {
1382 out_len = 0u;
1383 return ErrorCode::ARG_ERR;
1384 }
1385
1386 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_CONFIGURE);
1387 resp[1] = DAP_OK;
1388 out_len = 2u;
1389
1390 if (jtag_ == nullptr)
1391 {
1392 resp[1] = DAP_ERROR;
1393 return ErrorCode::OK;
1394 }
1395
1396 if (req_len < 2u)
1397 {
1398 resp[1] = DAP_ERROR;
1399 return ErrorCode::ARG_ERR;
1400 }
1401
1402 const uint8_t COUNT = req[1];
1403 if (COUNT > JTAG_MAX_DEVICES || req_len < static_cast<uint16_t>(2u + COUNT))
1404 {
1405 resp[1] = DAP_ERROR;
1406 return ErrorCode::ARG_ERR;
1407 }
1408
1409 Memory::FastSet(jtag_ir_len_, 0, sizeof(jtag_ir_len_));
1410
1411 uint32_t bits = 0u;
1412 for (uint32_t i = 0; i < COUNT; ++i)
1413 {
1414 const uint8_t LEN = req[static_cast<uint16_t>(2u + i)];
1415 jtag_ir_len_[i] = LEN;
1416 bits += LEN;
1417 }
1418
1419 jtag_chain_.count = COUNT;
1420 if (jtag_chain_.index >= jtag_chain_.count)
1421 {
1422 jtag_chain_.index = 0u;
1423 }
1424 jtag_chain_.ir_before_bits_len = 0u;
1425 jtag_chain_.ir_after_bits_len = 0u;
1426 jtag_chain_.dr_before_bits_len = 0u;
1427 jtag_chain_.dr_after_bits_len = 0u;
1428
1429 return ErrorCode::OK;
1430}
1431
1432template <typename SwdPort>
1433ErrorCode DapLinkV1Class<SwdPort>::HandleJTAGIdCode(bool /*in_isr*/, const uint8_t* req,
1434 uint16_t req_len, uint8_t* resp,
1435 uint16_t resp_cap, uint16_t& out_len)
1436{
1437 if (!req || !resp || resp_cap < 2u)
1438 {
1439 out_len = 0u;
1440 return ErrorCode::ARG_ERR;
1441 }
1442
1443 if (resp_cap < 6u)
1444 {
1445 out_len = 0u;
1446 return ErrorCode::NOT_FOUND;
1447 }
1448
1449 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_IDCODE);
1450 resp[1] = DAP_ERROR;
1451 out_len = 2u;
1452
1453 if (jtag_ == nullptr ||
1454 dap_state_.debug_port != LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
1455 {
1456 return ErrorCode::OK;
1457 }
1458
1459 if (req_len < 2u)
1460 {
1461 return ErrorCode::ARG_ERR;
1462 }
1463
1464 const uint8_t INDEX = req[1];
1465 if (INDEX >= jtag_chain_.count)
1466 {
1467 return ErrorCode::OK;
1468 }
1469
1470 jtag_chain_.index = INDEX;
1471 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
1472
1473 LibXR::Debug::JtagDp dp(*jtag_, &jtag_chain_);
1474 uint32_t idcode = 0u;
1475 ErrorCode EC = dp.ReadIdCode(idcode);
1476 if (EC == ErrorCode::OK &&
1477 (idcode == 0u || idcode == 0xFFFF'FFFFu || ((idcode & 0x1u) == 0u)) &&
1478 jtag_ir_len_[INDEX] != 4u)
1479 {
1480 uint32_t fallback_idcode = 0u;
1481 EC = dp.ReadIdCodeWithIr(0x01u, fallback_idcode);
1482 if (EC != ErrorCode::OK)
1483 {
1484 return EC;
1485 }
1486 if (fallback_idcode != 0u && fallback_idcode != 0xFFFF'FFFFu &&
1487 ((fallback_idcode & 0x1u) != 0u))
1488 {
1489 idcode = fallback_idcode;
1490 }
1491 }
1492 if (EC != ErrorCode::OK)
1493 {
1494 return EC;
1495 }
1496
1497 resp[1] = DAP_OK;
1498 resp[2] = static_cast<uint8_t>(idcode & 0xFFu);
1499 resp[3] = static_cast<uint8_t>((idcode >> 8) & 0xFFu);
1500 resp[4] = static_cast<uint8_t>((idcode >> 16) & 0xFFu);
1501 resp[5] = static_cast<uint8_t>((idcode >> 24) & 0xFFu);
1502 out_len = 6u;
1503 return ErrorCode::OK;
1504}
1505
1506template <typename SwdPort>
1507ErrorCode DapLinkV1Class<SwdPort>::HandleQueueCommands(bool /*in_isr*/,
1508 const uint8_t* /*req*/,
1509 uint16_t /*req_len*/,
1510 uint8_t* resp, uint16_t resp_cap,
1511 uint16_t& out_len)
1512{
1513 return build_cmd_status_response(
1514 to_u8(LibXR::USB::DapLinkV1Def::CommandId::QUEUE_COMMANDS), DAP_ERROR, resp,
1515 resp_cap, out_len);
1516}
1517
1518template <typename SwdPort>
1519ErrorCode DapLinkV1Class<SwdPort>::HandleExecuteCommands(bool /*in_isr*/,
1520 const uint8_t* /*req*/,
1521 uint16_t /*req_len*/,
1522 uint8_t* resp, uint16_t resp_cap,
1523 uint16_t& out_len)
1524{
1525 return build_cmd_status_response(
1526 to_u8(LibXR::USB::DapLinkV1Def::CommandId::EXECUTE_COMMANDS), DAP_ERROR, resp,
1527 resp_cap, out_len);
1528}
1529
1530template <typename SwdPort>
1531uint8_t DapLinkV1Class<SwdPort>::MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack) const
1532{
1533 switch (ack)
1534 {
1535 case LibXR::Debug::SwdProtocol::Ack::OK:
1536 return 1u;
1537 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1538 return 2u;
1539 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1540 return 4u;
1541 case LibXR::Debug::SwdProtocol::Ack::NO_ACK:
1542 case LibXR::Debug::SwdProtocol::Ack::PROTOCOL:
1543 default:
1544 return 7u;
1545 }
1546}
1547
1548template <typename SwdPort>
1549uint8_t DapLinkV1Class<SwdPort>::MapAckToDapResp(
1550 LibXR::Debug::JtagProtocol::Ack ack) const
1551{
1552 switch (ack)
1553 {
1554 case LibXR::Debug::JtagProtocol::Ack::OK:
1555 return 1u;
1556 case LibXR::Debug::JtagProtocol::Ack::WAIT:
1557 return 2u;
1558 case LibXR::Debug::JtagProtocol::Ack::FAULT:
1559 return 4u;
1560 case LibXR::Debug::JtagProtocol::Ack::NO_ACK:
1561 case LibXR::Debug::JtagProtocol::Ack::PROTOCOL:
1562 default:
1563 return 7u;
1564 }
1565}
1566
1567template <typename SwdPort>
1568void DapLinkV1Class<SwdPort>::SetTransferAbortFlag(bool on)
1569{
1570 dap_state_.transfer_abort = on;
1571}
1572
1573template <typename SwdPort>
1574ErrorCode DapLinkV1Class<SwdPort>::HandleTransfer(bool /*in_isr*/, const uint8_t* req,
1575 uint16_t req_len, uint8_t* resp,
1576 uint16_t resp_cap, uint16_t& out_len)
1577{
1578 out_len = 0u;
1579 if (!req || !resp || resp_cap < 3u)
1580 {
1581 return ErrorCode::ARG_ERR;
1582 }
1583
1584 if constexpr (JTAG_ENABLED)
1585 {
1586 if (dap_state_.debug_port == LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
1587 {
1588 return HandleJtagTransfer(false, req, req_len, resp, resp_cap, out_len);
1589 }
1590 }
1591
1592 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER);
1593 resp[1] = 0u;
1594 resp[2] = 0u;
1595 uint16_t resp_off = 3u;
1596
1597 if (req_len < 3u)
1598 {
1599 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1600 out_len = 3u;
1601 return ErrorCode::ARG_ERR;
1602 }
1603
1604 if (dap_state_.transfer_abort)
1605 {
1606 dap_state_.transfer_abort = false;
1607 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1608 out_len = 3u;
1609 return ErrorCode::OK;
1610 }
1611
1612 const uint8_t COUNT = req[2];
1613 uint16_t req_off = 3u;
1614
1615 auto ack_to_dap = [&](LibXR::Debug::SwdProtocol::Ack ack) -> uint8_t
1616 {
1617 switch (ack)
1618 {
1619 case LibXR::Debug::SwdProtocol::Ack::OK:
1620 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1621 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1622 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_WAIT;
1623 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1624 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_FAULT;
1625 default:
1626 return 0x07u;
1627 }
1628 };
1629
1630 auto push_u32 = [&](uint32_t VALUE) -> bool
1631 {
1632 if (resp_off + 4u > resp_cap)
1633 {
1634 return false;
1635 }
1636 Memory::FastCopy(&resp[resp_off], &VALUE, sizeof(VALUE));
1637 resp_off = static_cast<uint16_t>(resp_off + 4u);
1638 return true;
1639 };
1640
1641 auto push_timestamp = [&]() -> bool
1642 {
1643 const uint32_t T = static_cast<uint32_t>(LibXR::Timebase::GetMicroseconds());
1644 return push_u32(T);
1645 };
1646
1647 auto ensure_space = [&](uint16_t bytes) -> bool
1648 { return (resp_off + bytes) <= resp_cap; };
1649
1650 auto bytes_for_read = [&](bool need_ts) -> uint16_t
1651 { return static_cast<uint16_t>(need_ts ? 8u : 4u); };
1652
1653 uint8_t response_count = 0u;
1654 uint8_t response_value = 0u;
1655 bool check_write = false;
1656
1657 struct PendingApRead
1658 {
1659 bool valid = false;
1660 bool need_ts = false;
1661 } pending;
1662
1663 auto emit_read_with_ts = [&](bool need_ts, uint32_t data) -> bool
1664 {
1665 if (need_ts)
1666 {
1667 if (!push_timestamp())
1668 {
1669 return false;
1670 }
1671 }
1672 if (!push_u32(data))
1673 {
1674 return false;
1675 }
1676 response_count++;
1677 return true;
1678 };
1679
1680 auto complete_pending_by_rdbuff = [&]() -> bool
1681 {
1682 if (!pending.valid)
1683 {
1684 return true;
1685 }
1686
1687 if (!ensure_space(bytes_for_read(pending.need_ts)))
1688 {
1689 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1690 return false;
1691 }
1692
1693 uint32_t rdata = 0u;
1694 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1695 const ErrorCode EC = swd_.DpReadRdbuffTxn(rdata, ack);
1696
1697 const uint8_t V = ack_to_dap(ack);
1698 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1699 {
1700 response_value = V;
1701 return false;
1702 }
1703 if (EC != ErrorCode::OK)
1704 {
1705 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1706 return false;
1707 }
1708
1709 if (!emit_read_with_ts(pending.need_ts, rdata))
1710 {
1711 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1712 return false;
1713 }
1714
1715 pending.valid = false;
1716 pending.need_ts = false;
1717 check_write = false;
1718 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1719 return true;
1720 };
1721
1722 auto flush_pending_if_any = [&]() -> bool
1723 { return pending.valid ? complete_pending_by_rdbuff() : true; };
1724
1725 for (uint32_t i = 0; i < COUNT; ++i)
1726 {
1727 if (req_off >= req_len)
1728 {
1729 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1730 break;
1731 }
1732
1733 const uint8_t RQ = req[req_off++];
1734
1735 const bool AP = LibXR::USB::DapLinkV1Def::req_is_ap(RQ);
1736 const bool RNW = LibXR::USB::DapLinkV1Def::req_is_read(RQ);
1737 const uint8_t ADDR2B = LibXR::USB::DapLinkV1Def::req_addr2b(RQ);
1738
1740 const bool MATCH_VALUE =
1741 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
1742 const bool MATCH_MASK =
1743 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK) != 0u);
1744
1745 if (TS && (MATCH_VALUE || MATCH_MASK))
1746 {
1747 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1748 break;
1749 }
1750
1751 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1753
1754 if (!RNW)
1755 {
1756 if (!flush_pending_if_any())
1757 {
1758 break;
1759 }
1760
1761 if (req_off + 4u > req_len)
1762 {
1763 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1764 break;
1765 }
1766
1767 uint32_t wdata = 0u;
1768 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
1769 req_off = static_cast<uint16_t>(req_off + 4u);
1770
1771 if (MATCH_MASK)
1772 {
1773 match_mask_ = wdata;
1774 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1775 response_count++;
1776 continue;
1777 }
1778
1779 if (AP)
1780 {
1781 EC = swd_.ApWriteTxn(ADDR2B, wdata, ack);
1782 }
1783 else
1784 {
1785 EC = swd_.DpWriteTxn(static_cast<LibXR::Debug::SwdProtocol::DpWriteReg>(ADDR2B),
1786 wdata, ack);
1787 }
1788
1789 response_value = ack_to_dap(ack);
1790 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1791 {
1792 break;
1793 }
1794 if (EC != ErrorCode::OK)
1795 {
1796 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1797 break;
1798 }
1799
1800 if (TS)
1801 {
1802 if (!push_timestamp())
1803 {
1804 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1805 break;
1806 }
1807 }
1808
1809 response_count++;
1810 check_write = true;
1811 }
1812 else
1813 {
1814 if (MATCH_VALUE)
1815 {
1816 if (!flush_pending_if_any())
1817 {
1818 break;
1819 }
1820
1821 if (req_off + 4u > req_len)
1822 {
1823 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1824 break;
1825 }
1826
1827 uint32_t match_val = 0u;
1828 Memory::FastCopy(&match_val, &req[req_off], sizeof(match_val));
1829 req_off = static_cast<uint16_t>(req_off + 4u);
1830
1831 uint32_t rdata = 0u;
1832 uint32_t retry = dap_state_.transfer_cfg.match_retry;
1833 bool matched = false;
1834
1835 while (true)
1836 {
1837 if (AP)
1838 {
1839 EC = swd_.ApReadTxn(ADDR2B, rdata, ack);
1840 if (EC == ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1841 {
1842 check_write = false;
1843 }
1844 }
1845 else
1846 {
1847 EC = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
1848 rdata, ack);
1849 }
1850
1851 response_value = ack_to_dap(ack);
1852 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1853 {
1854 break;
1855 }
1856 if (EC != ErrorCode::OK)
1857 {
1858 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1859 break;
1860 }
1861
1862 if ((rdata & match_mask_) == (match_val & match_mask_))
1863 {
1864 matched = true;
1865 break;
1866 }
1867
1868 if (retry == 0u)
1869 {
1870 break;
1871 }
1872 --retry;
1873 }
1874
1875 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1876 {
1877 break;
1878 }
1879
1880 if (!matched)
1881 {
1882 response_value =
1883 static_cast<uint8_t>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
1884 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
1885 break;
1886 }
1887
1888 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1889 response_count++;
1890 continue;
1891 }
1892
1893 if (!AP)
1894 {
1895 if (!flush_pending_if_any())
1896 {
1897 break;
1898 }
1899
1900 uint32_t rdata = 0u;
1901 EC = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
1902 rdata, ack);
1903
1904 response_value = ack_to_dap(ack);
1905 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1906 {
1907 break;
1908 }
1909 if (EC != ErrorCode::OK)
1910 {
1911 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1912 break;
1913 }
1914
1915 if (!ensure_space(bytes_for_read(TS)))
1916 {
1917 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1918 break;
1919 }
1920
1921 if (!emit_read_with_ts(TS, rdata))
1922 {
1923 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1924 break;
1925 }
1926
1927 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1928 continue;
1929 }
1930
1931 if (!pending.valid)
1932 {
1933 uint32_t dummy_posted = 0u;
1934 EC = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
1935
1936 response_value = ack_to_dap(ack);
1937 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1938 {
1939 break;
1940 }
1941 if (EC != ErrorCode::OK)
1942 {
1943 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1944 break;
1945 }
1946
1947 pending.valid = true;
1948 pending.need_ts = TS;
1949 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1950 }
1951 else
1952 {
1953 if (!ensure_space(bytes_for_read(pending.need_ts)))
1954 {
1955 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1956 break;
1957 }
1958
1959 uint32_t posted_prev = 0u;
1960 EC = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
1961
1962 const uint8_t CUR_V = ack_to_dap(ack);
1963 if (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK || EC != ErrorCode::OK)
1964 {
1965 const uint8_t PRIOR_FAIL = (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1966 ? CUR_V
1967 : LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1968
1969 if (!complete_pending_by_rdbuff())
1970 {
1971 break;
1972 }
1973
1974 response_value = PRIOR_FAIL;
1975 break;
1976 }
1977
1978 if (!emit_read_with_ts(pending.need_ts, posted_prev))
1979 {
1980 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1981 break;
1982 }
1983
1984 pending.valid = true;
1985 pending.need_ts = TS;
1986 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1987 }
1988 }
1989
1990 if (dap_state_.transfer_abort)
1991 {
1992 dap_state_.transfer_abort = false;
1993 break;
1994 }
1995 }
1996
1997 if (pending.valid)
1998 {
1999 const uint8_t PRIOR_FAIL = response_value;
2000
2001 if (!complete_pending_by_rdbuff())
2002 {
2003 }
2004 else
2005 {
2006 if (PRIOR_FAIL != 0u && PRIOR_FAIL != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2007 {
2008 response_value = PRIOR_FAIL;
2009 }
2010 }
2011 }
2012
2013 if (response_value == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK && check_write)
2014 {
2015 uint32_t dummy = 0u;
2016 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2017 const ErrorCode EC = swd_.DpReadRdbuffTxn(dummy, ack);
2018 const uint8_t V = ack_to_dap(ack);
2019
2020 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2021 {
2022 response_value = V;
2023 }
2024 else if (EC != ErrorCode::OK)
2025 {
2026 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2027 }
2028 }
2029
2030 resp[1] = response_count;
2031 resp[2] = response_value;
2032 out_len = resp_off;
2033 return ErrorCode::OK;
2034}
2035
2036template <typename SwdPort>
2037ErrorCode DapLinkV1Class<SwdPort>::HandleTransferBlock(bool /*in_isr*/,
2038 const uint8_t* req,
2039 uint16_t req_len, uint8_t* resp,
2040 uint16_t resp_cap,
2041 uint16_t& out_len)
2042{
2043 if constexpr (JTAG_ENABLED)
2044 {
2045 if (dap_state_.debug_port == LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
2046 {
2047 return HandleJtagTransferBlock(false, req, req_len, resp, resp_cap, out_len);
2048 }
2049 }
2050
2051 if (!resp || resp_cap < 4u)
2052 {
2053 out_len = 0u;
2054 return ErrorCode::NOT_FOUND;
2055 }
2056
2057 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK);
2058 resp[1] = 0u;
2059 resp[2] = 0u;
2060 resp[3] = 0u;
2061 out_len = 4u;
2062
2063 if (!req || req_len < 5u)
2064 {
2065 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2066 return ErrorCode::ARG_ERR;
2067 }
2068
2069 if (dap_state_.transfer_abort)
2070 {
2071 dap_state_.transfer_abort = false;
2072 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2073 return ErrorCode::OK;
2074 }
2075
2076 uint16_t count = 0u;
2077 Memory::FastCopy(&count, &req[2], sizeof(count));
2078
2079 const uint8_t DAP_RQ = req[4];
2080
2081 if ((DAP_RQ & (LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE |
2082 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
2083 {
2084 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2086 }
2088 {
2089 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2091 }
2092
2093 if (count == 0u)
2094 {
2095 const uint16_t DONE0 = 0u;
2096 Memory::FastCopy(&resp[1], &DONE0, sizeof(DONE0));
2097 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2098 out_len = 4u;
2099 return ErrorCode::OK;
2100 }
2101
2102 const bool AP = LibXR::USB::DapLinkV1Def::req_is_ap(DAP_RQ);
2103 const bool RNW = LibXR::USB::DapLinkV1Def::req_is_read(DAP_RQ);
2104 const uint8_t ADDR2B = LibXR::USB::DapLinkV1Def::req_addr2b(DAP_RQ);
2105
2106 uint16_t done = 0u;
2107 uint8_t xresp = 0u;
2108
2109 uint16_t req_off = 5u;
2110 uint16_t resp_off = 4u;
2111
2112 if (!RNW)
2113 {
2114 for (uint32_t i = 0; i < count; ++i)
2115 {
2116 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2118
2119 if (req_off + 4u > req_len)
2120 {
2121 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2122 break;
2123 }
2124
2125 uint32_t wdata = 0u;
2126 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
2127 req_off = static_cast<uint16_t>(req_off + 4u);
2128
2129 if (AP)
2130 {
2131 EC = swd_.ApWriteTxn(ADDR2B, wdata, ack);
2132 }
2133 else
2134 {
2135 EC = swd_.DpWriteTxn(static_cast<LibXR::Debug::SwdProtocol::DpWriteReg>(ADDR2B),
2136 wdata, ack);
2137 }
2138
2139 xresp = MapAckToDapResp(ack);
2140 if (xresp == 0u)
2141 {
2142 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2143 break;
2144 }
2145
2146 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2147 {
2148 break;
2149 }
2150
2151 if (EC != ErrorCode::OK)
2152 {
2153 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2154 break;
2155 }
2156
2157 done = static_cast<uint16_t>(i + 1u);
2158 }
2159
2160 Memory::FastCopy(&resp[1], &done, sizeof(done));
2161 resp[3] = xresp;
2162 out_len = resp_off;
2163 return ErrorCode::OK;
2164 }
2165
2166 if (!AP)
2167 {
2168 for (uint32_t i = 0; i < count; ++i)
2169 {
2170 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2172 uint32_t rdata = 0u;
2173
2174 if (resp_off + 4u > resp_cap)
2175 {
2176 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2177 break;
2178 }
2179
2180 EC = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
2181 rdata, ack);
2182
2183 xresp = MapAckToDapResp(ack);
2184 if (xresp == 0u)
2185 {
2186 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2187 break;
2188 }
2189
2190 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2191 {
2192 break;
2193 }
2194
2195 if (EC != ErrorCode::OK)
2196 {
2197 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2198 break;
2199 }
2200
2201 Memory::FastCopy(&resp[resp_off], &rdata, sizeof(rdata));
2202 resp_off = static_cast<uint16_t>(resp_off + 4u);
2203 done = static_cast<uint16_t>(i + 1u);
2204 }
2205
2206 Memory::FastCopy(&resp[1], &done, sizeof(done));
2207 resp[3] = xresp;
2208 out_len = resp_off;
2209 return ErrorCode::OK;
2210 }
2211
2212 {
2213 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2215
2216 uint32_t dummy_posted = 0u;
2217 EC = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
2218 xresp = MapAckToDapResp(ack);
2219
2220 if (xresp == 0u)
2221 {
2222 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2223 goto out_ap_read; // NOLINT
2224 }
2225 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2226 {
2227 goto out_ap_read; // NOLINT
2228 }
2229 if (EC != ErrorCode::OK)
2230 {
2231 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2232 goto out_ap_read; // NOLINT
2233 }
2234
2235 for (uint32_t i = 1; i < count; ++i)
2236 {
2237 if (resp_off + 4u > resp_cap)
2238 {
2239 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2240 goto out_ap_read; // NOLINT
2241 }
2242
2243 uint32_t posted_prev = 0u;
2244 EC = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
2245 const uint8_t CUR = MapAckToDapResp(ack);
2246
2247 if (CUR == 0u)
2248 {
2249 xresp = CUR | LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2250 goto out_ap_read; // NOLINT
2251 }
2252
2253 if (ack != LibXR::Debug::SwdProtocol::Ack::OK || EC != ErrorCode::OK)
2254 {
2255 if (resp_off + 4u <= resp_cap)
2256 {
2257 uint32_t last = 0u;
2258 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2259 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2260 const uint8_t V2 = MapAckToDapResp(ack2);
2261
2262 if (V2 == 1u && EC2 == ErrorCode::OK)
2263 {
2264 Memory::FastCopy(&resp[resp_off], &last, sizeof(last));
2265 resp_off = static_cast<uint16_t>(resp_off + 4u);
2266 done = static_cast<uint16_t>(i);
2267 }
2268 else
2269 {
2270 xresp = V2;
2271 if (EC2 != ErrorCode::OK)
2272 {
2273 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2274 }
2275 goto out_ap_read; // NOLINT
2276 }
2277 }
2278
2279 xresp = CUR;
2280 if (EC != ErrorCode::OK)
2281 {
2282 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2283 }
2284 goto out_ap_read; // NOLINT
2285 }
2286
2287 Memory::FastCopy(&resp[resp_off], &posted_prev, sizeof(posted_prev));
2288 resp_off = static_cast<uint16_t>(resp_off + 4u);
2289 done = static_cast<uint16_t>(i);
2290 xresp = CUR;
2291 }
2292
2293 if (resp_off + 4u > resp_cap)
2294 {
2295 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2296 goto out_ap_read; // NOLINT
2297 }
2298
2299 {
2300 uint32_t last = 0u;
2301 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2302 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2303 const uint8_t V2 = MapAckToDapResp(ack2);
2304
2305 xresp = V2;
2306 if (V2 != 1u)
2307 {
2308 goto out_ap_read; // NOLINT
2309 }
2310 if (EC2 != ErrorCode::OK)
2311 {
2312 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2313 goto out_ap_read; // NOLINT
2314 }
2315
2316 Memory::FastCopy(&resp[resp_off], &last, sizeof(last));
2317 resp_off = static_cast<uint16_t>(resp_off + 4u);
2318 done = count;
2319 }
2320
2321 out_ap_read:
2322 Memory::FastCopy(&resp[1], &done, sizeof(done));
2323 resp[3] = xresp;
2324 out_len = resp_off;
2325 return ErrorCode::OK;
2326 }
2327}
2328
2329template <typename SwdPort>
2330ErrorCode DapLinkV1Class<SwdPort>::HandleJtagTransfer(bool /*in_isr*/, const uint8_t* req,
2331 uint16_t req_len, uint8_t* resp,
2332 uint16_t resp_cap,
2333 uint16_t& out_len)
2334{
2335 out_len = 0u;
2336 if (!req || !resp || resp_cap < 3u)
2337 {
2338 return ErrorCode::ARG_ERR;
2339 }
2340
2341 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER);
2342 resp[1] = 0u;
2343 resp[2] = 0u;
2344 uint16_t resp_off = 3u;
2345
2346 if (req_len < 3u || jtag_ == nullptr || jtag_chain_.count == 0u)
2347 {
2348 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2349 out_len = 3u;
2350 return ErrorCode::OK;
2351 }
2352
2353 if (dap_state_.transfer_abort)
2354 {
2355 dap_state_.transfer_abort = false;
2356 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2357 out_len = 3u;
2358 return ErrorCode::OK;
2359 }
2360
2361 const uint8_t TAP_INDEX = req[1];
2362 if (TAP_INDEX >= jtag_chain_.count)
2363 {
2364 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2365 out_len = 3u;
2366 return ErrorCode::OK;
2367 }
2368
2369 jtag_chain_.index = TAP_INDEX;
2370 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
2371
2372 LibXR::Debug::JtagDp dp(*jtag_, &jtag_chain_);
2373
2374 const uint8_t COUNT = req[2];
2375 uint16_t req_off = 3u;
2376
2377 auto push_u32 = [&](uint32_t VALUE) -> bool
2378 {
2379 if (resp_off + 4u > resp_cap)
2380 {
2381 return false;
2382 }
2383 Memory::FastCopy(&resp[resp_off], &VALUE, sizeof(VALUE));
2384 resp_off = static_cast<uint16_t>(resp_off + 4u);
2385 return true;
2386 };
2387
2388 auto push_timestamp = [&]() -> bool
2389 {
2390 const uint32_t T = static_cast<uint32_t>(LibXR::Timebase::GetMicroseconds());
2391 return push_u32(T);
2392 };
2393
2394 auto ensure_space = [&](uint16_t bytes) -> bool
2395 { return (resp_off + bytes) <= resp_cap; };
2396
2397 auto bytes_for_read = [&](bool need_ts) -> uint16_t
2398 { return static_cast<uint16_t>(need_ts ? 8u : 4u); };
2399
2400 auto idle_after_attempt = [&]()
2401 {
2402 if (dap_state_.transfer_cfg.idle_cycles != 0u)
2403 {
2404 jtag_->IdleClocks(dap_state_.transfer_cfg.idle_cycles);
2405 }
2406 };
2407
2408 auto dp_read_retry = [&](uint8_t addr2b, uint32_t& val,
2409 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2410 {
2411 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2412 while (true)
2413 {
2414 const ErrorCode EC = dp.DpReadTxn(addr2b, val, ack);
2415 idle_after_attempt();
2416 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2417 dap_state_.transfer_abort)
2418 {
2419 return EC;
2420 }
2421 --retry;
2422 }
2423 };
2424
2425 auto dp_write_retry = [&](uint8_t addr2b, uint32_t val,
2426 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2427 {
2428 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2429 while (true)
2430 {
2431 const ErrorCode EC = dp.DpWriteTxn(addr2b, val, ack);
2432 idle_after_attempt();
2433 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2434 dap_state_.transfer_abort)
2435 {
2436 return EC;
2437 }
2438 --retry;
2439 }
2440 };
2441
2442 auto ap_read_retry = [&](uint8_t addr2b, uint32_t& val,
2443 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2444 {
2445 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2446 while (true)
2447 {
2448 const ErrorCode EC = dp.ApReadTxn(addr2b, val, ack);
2449 idle_after_attempt();
2450 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2451 dap_state_.transfer_abort)
2452 {
2453 return EC;
2454 }
2455 --retry;
2456 }
2457 };
2458
2459 auto ap_write_retry = [&](uint8_t addr2b, uint32_t val,
2460 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2461 {
2462 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2463 while (true)
2464 {
2465 const ErrorCode EC = dp.ApWriteTxn(addr2b, val, ack);
2466 idle_after_attempt();
2467 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2468 dap_state_.transfer_abort)
2469 {
2470 return EC;
2471 }
2472 --retry;
2473 }
2474 };
2475
2476 auto check_posted_ap_write_jtag = [&](LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2477 {
2478 uint32_t ctrl_stat = 0u;
2479 return dp_read_retry(
2480 static_cast<uint8_t>(LibXR::Debug::SwdProtocol::DpReadReg::CTRL_STAT), ctrl_stat,
2481 ack);
2482 };
2483
2484 uint8_t response_count = 0u;
2485 uint8_t response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2486 bool pending_ap_write = false;
2487
2488 auto check_posted_ap_write_if_pending = [&]() -> bool
2489 {
2490 if (!pending_ap_write)
2491 {
2492 return true;
2493 }
2494
2495 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2496 const ErrorCode EC = check_posted_ap_write_jtag(ack);
2497 const uint8_t V = MapAckToDapResp(ack);
2498
2499 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2500 {
2501 response_value = V;
2502 return false;
2503 }
2504 if (EC != ErrorCode::OK)
2505 {
2506 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2507 return false;
2508 }
2509
2510 pending_ap_write = false;
2511 return true;
2512 };
2513
2514 auto should_check_pending_ap_write_at_tail = [&]() -> bool
2515 {
2516 return response_value == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK ||
2517 response_value ==
2518 static_cast<uint8_t>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
2519 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
2520 };
2521
2522 auto emit_read_with_ts = [&](bool need_ts, uint32_t data) -> bool
2523 {
2524 if (need_ts)
2525 {
2526 if (!push_timestamp())
2527 {
2528 return false;
2529 }
2530 }
2531 if (!push_u32(data))
2532 {
2533 return false;
2534 }
2535 response_count++;
2536 return true;
2537 };
2538
2539 for (uint32_t i = 0; i < COUNT; ++i)
2540 {
2541 if (req_off >= req_len)
2542 {
2543 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2544 break;
2545 }
2546
2547 const uint8_t RQ = req[req_off++];
2548 const bool AP = LibXR::USB::DapLinkV1Def::req_is_ap(RQ);
2549 const bool RNW = LibXR::USB::DapLinkV1Def::req_is_read(RQ);
2550 const uint8_t ADDR2B = LibXR::USB::DapLinkV1Def::req_addr2b(RQ);
2551
2553 const bool MATCH_VALUE =
2554 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
2555 const bool MATCH_MASK =
2556 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK) != 0u);
2557
2558 if (TS && (MATCH_VALUE || MATCH_MASK))
2559 {
2560 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2561 break;
2562 }
2563
2564 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2566
2567 if (!RNW)
2568 {
2569 if (req_off + 4u > req_len)
2570 {
2571 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2572 break;
2573 }
2574
2575 uint32_t wdata = 0u;
2576 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
2577 req_off = static_cast<uint16_t>(req_off + 4u);
2578
2579 if (MATCH_MASK)
2580 {
2581 match_mask_ = wdata;
2582 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2583 response_count++;
2584 continue;
2585 }
2586
2587 if (AP)
2588 {
2589 EC = ap_write_retry(ADDR2B, wdata, ack);
2590 }
2591 else
2592 {
2593 EC = dp_write_retry(ADDR2B, wdata, ack);
2594 }
2595
2596 response_value = MapAckToDapResp(ack);
2597 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2598 {
2599 break;
2600 }
2601 if (EC != ErrorCode::OK)
2602 {
2603 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2604 break;
2605 }
2606
2607 if (TS)
2608 {
2609 if (!push_timestamp())
2610 {
2611 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2612 break;
2613 }
2614 }
2615
2616 response_count++;
2617 if (AP)
2618 {
2619 pending_ap_write = true;
2620 }
2621 }
2622 else
2623 {
2624 if (MATCH_VALUE)
2625 {
2626 if (!check_posted_ap_write_if_pending())
2627 {
2628 break;
2629 }
2630
2631 if (req_off + 4u > req_len)
2632 {
2633 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2634 break;
2635 }
2636
2637 uint32_t match_val = 0u;
2638 Memory::FastCopy(&match_val, &req[req_off], sizeof(match_val));
2639 req_off = static_cast<uint16_t>(req_off + 4u);
2640
2641 uint32_t rdata = 0u;
2642 uint32_t retry = dap_state_.transfer_cfg.match_retry;
2643 bool matched = false;
2644
2645 while (true)
2646 {
2647 if (AP)
2648 {
2649 EC = ap_read_retry(ADDR2B, rdata, ack);
2650 }
2651 else
2652 {
2653 EC = dp_read_retry(ADDR2B, rdata, ack);
2654 }
2655
2656 response_value = MapAckToDapResp(ack);
2657 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2658 {
2659 break;
2660 }
2661 if (EC != ErrorCode::OK)
2662 {
2663 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2664 break;
2665 }
2666
2667 if ((rdata & match_mask_) == (match_val & match_mask_))
2668 {
2669 matched = true;
2670 break;
2671 }
2672
2673 if (retry == 0u)
2674 {
2675 break;
2676 }
2677 --retry;
2678 }
2679
2680 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2681 {
2682 break;
2683 }
2684
2685 if (!matched)
2686 {
2687 response_value =
2688 static_cast<uint8_t>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
2689 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
2690 break;
2691 }
2692
2693 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2694 response_count++;
2695 continue;
2696 }
2697
2698 uint32_t rdata = 0u;
2699 if (!check_posted_ap_write_if_pending())
2700 {
2701 break;
2702 }
2703
2704 if (AP)
2705 {
2706 EC = ap_read_retry(ADDR2B, rdata, ack);
2707 }
2708 else
2709 {
2710 EC = dp_read_retry(ADDR2B, rdata, ack);
2711 }
2712
2713 response_value = MapAckToDapResp(ack);
2714 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2715 {
2716 break;
2717 }
2718 if (EC != ErrorCode::OK)
2719 {
2720 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2721 break;
2722 }
2723
2724 if (!ensure_space(bytes_for_read(TS)))
2725 {
2726 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2727 break;
2728 }
2729
2730 if (!emit_read_with_ts(TS, rdata))
2731 {
2732 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2733 break;
2734 }
2735
2736 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2737 }
2738
2739 if (dap_state_.transfer_abort)
2740 {
2741 dap_state_.transfer_abort = false;
2742 break;
2743 }
2744 }
2745
2746 if (pending_ap_write && should_check_pending_ap_write_at_tail())
2747 {
2748 const uint8_t PRIOR_RESPONSE = response_value;
2749 if (check_posted_ap_write_if_pending())
2750 {
2751 response_value = PRIOR_RESPONSE;
2752 }
2753 }
2754
2755 resp[1] = response_count;
2756 resp[2] = response_value;
2757 out_len = resp_off;
2758 return ErrorCode::OK;
2759}
2760
2761template <typename SwdPort>
2762ErrorCode DapLinkV1Class<SwdPort>::HandleJtagTransferBlock(
2763 bool /*in_isr*/, const uint8_t* req, uint16_t req_len, uint8_t* resp,
2764 uint16_t resp_cap, uint16_t& out_len)
2765{
2766 if (!resp || resp_cap < 4u)
2767 {
2768 out_len = 0u;
2769 return ErrorCode::NOT_FOUND;
2770 }
2771
2772 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK);
2773 resp[1] = 0u;
2774 resp[2] = 0u;
2775 resp[3] = 0u;
2776 out_len = 4u;
2777
2778 if (!req || req_len < 5u || jtag_ == nullptr || jtag_chain_.count == 0u)
2779 {
2780 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2781 return ErrorCode::ARG_ERR;
2782 }
2783
2784 if (dap_state_.transfer_abort)
2785 {
2786 dap_state_.transfer_abort = false;
2787 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2788 return ErrorCode::OK;
2789 }
2790
2791 const uint8_t TAP_INDEX = req[1];
2792 if (TAP_INDEX >= jtag_chain_.count)
2793 {
2794 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2795 return ErrorCode::OK;
2796 }
2797
2798 jtag_chain_.index = TAP_INDEX;
2799 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
2800
2801 uint16_t count = 0u;
2802 Memory::FastCopy(&count, &req[2], sizeof(count));
2803
2804 const uint8_t DAP_RQ = req[4];
2805
2806 if ((DAP_RQ & (LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE |
2807 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
2808 {
2809 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2811 }
2813 {
2814 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2816 }
2817
2818 if (count == 0u)
2819 {
2820 const uint16_t DONE0 = 0u;
2821 Memory::FastCopy(&resp[1], &DONE0, sizeof(DONE0));
2822 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2823 out_len = 4u;
2824 return ErrorCode::OK;
2825 }
2826
2827 LibXR::Debug::JtagDp dp(*jtag_, &jtag_chain_);
2828
2829 auto idle_after_attempt = [&]()
2830 {
2831 if (dap_state_.transfer_cfg.idle_cycles != 0u)
2832 {
2833 jtag_->IdleClocks(dap_state_.transfer_cfg.idle_cycles);
2834 }
2835 };
2836
2837 auto dp_read_retry = [&](uint8_t addr2b, uint32_t& val,
2838 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2839 {
2840 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2841 while (true)
2842 {
2843 const ErrorCode EC = dp.DpReadTxn(addr2b, val, ack);
2844 idle_after_attempt();
2845 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2846 dap_state_.transfer_abort)
2847 {
2848 return EC;
2849 }
2850 --retry;
2851 }
2852 };
2853
2854 auto dp_write_retry = [&](uint8_t addr2b, uint32_t val,
2855 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2856 {
2857 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2858 while (true)
2859 {
2860 const ErrorCode EC = dp.DpWriteTxn(addr2b, val, ack);
2861 idle_after_attempt();
2862 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2863 dap_state_.transfer_abort)
2864 {
2865 return EC;
2866 }
2867 --retry;
2868 }
2869 };
2870
2871 auto ap_read_retry = [&](uint8_t addr2b, uint32_t& val,
2872 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2873 {
2874 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2875 while (true)
2876 {
2877 const ErrorCode EC = dp.ApReadTxn(addr2b, val, ack);
2878 idle_after_attempt();
2879 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2880 dap_state_.transfer_abort)
2881 {
2882 return EC;
2883 }
2884 --retry;
2885 }
2886 };
2887
2888 auto ap_write_retry = [&](uint8_t addr2b, uint32_t val,
2889 LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2890 {
2891 uint32_t retry = dap_state_.transfer_cfg.retry_count;
2892 while (true)
2893 {
2894 const ErrorCode EC = dp.ApWriteTxn(addr2b, val, ack);
2895 idle_after_attempt();
2896 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2897 dap_state_.transfer_abort)
2898 {
2899 return EC;
2900 }
2901 --retry;
2902 }
2903 };
2904
2905 auto check_posted_ap_write_jtag = [&](LibXR::Debug::JtagProtocol::Ack& ack) -> ErrorCode
2906 {
2907 uint32_t ctrl_stat = 0u;
2908 return dp_read_retry(
2909 static_cast<uint8_t>(LibXR::Debug::SwdProtocol::DpReadReg::CTRL_STAT), ctrl_stat,
2910 ack);
2911 };
2912
2913 const bool AP = LibXR::USB::DapLinkV1Def::req_is_ap(DAP_RQ);
2914 const bool RNW = LibXR::USB::DapLinkV1Def::req_is_read(DAP_RQ);
2915 const uint8_t ADDR2B = LibXR::USB::DapLinkV1Def::req_addr2b(DAP_RQ);
2916
2917 uint16_t done = 0u;
2918 uint8_t xresp = 0u;
2919
2920 uint16_t req_off = 5u;
2921 uint16_t resp_off = 4u;
2922
2923 if (!RNW)
2924 {
2925 for (uint32_t i = 0; i < count; ++i)
2926 {
2927 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2929
2930 if (req_off + 4u > req_len)
2931 {
2932 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2933 break;
2934 }
2935
2936 uint32_t wdata = 0u;
2937 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
2938 req_off = static_cast<uint16_t>(req_off + 4u);
2939
2940 if (AP)
2941 {
2942 EC = ap_write_retry(ADDR2B, wdata, ack);
2943 }
2944 else
2945 {
2946 EC = dp_write_retry(ADDR2B, wdata, ack);
2947 }
2948
2949 xresp = MapAckToDapResp(ack);
2950 if (xresp == 0u)
2951 {
2952 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2953 break;
2954 }
2955
2956 if (ack != LibXR::Debug::JtagProtocol::Ack::OK)
2957 {
2958 break;
2959 }
2960
2961 if (EC != ErrorCode::OK)
2962 {
2963 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2964 break;
2965 }
2966
2967 done = static_cast<uint16_t>(i + 1u);
2968 }
2969
2970 if (AP && xresp == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK && done > 0u)
2971 {
2972 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2973 const ErrorCode EC = check_posted_ap_write_jtag(ack);
2974 const uint8_t V = MapAckToDapResp(ack);
2975 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2976 {
2977 xresp = V;
2978 }
2979 else if (EC != ErrorCode::OK)
2980 {
2981 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2982 }
2983 }
2984
2985 Memory::FastCopy(&resp[1], &done, sizeof(done));
2986 resp[3] = xresp;
2987 out_len = resp_off;
2988 return ErrorCode::OK;
2989 }
2990
2991 for (uint32_t i = 0; i < count; ++i)
2992 {
2993 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2995 uint32_t rdata = 0u;
2996
2997 if (resp_off + 4u > resp_cap)
2998 {
2999 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
3000 break;
3001 }
3002
3003 if (AP)
3004 {
3005 EC = ap_read_retry(ADDR2B, rdata, ack);
3006 }
3007 else
3008 {
3009 EC = dp_read_retry(ADDR2B, rdata, ack);
3010 }
3011
3012 xresp = MapAckToDapResp(ack);
3013 if (xresp == 0u)
3014 {
3015 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
3016 break;
3017 }
3018
3019 if (ack != LibXR::Debug::JtagProtocol::Ack::OK)
3020 {
3021 break;
3022 }
3023
3024 if (EC != ErrorCode::OK)
3025 {
3026 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
3027 break;
3028 }
3029
3030 Memory::FastCopy(&resp[resp_off], &rdata, sizeof(rdata));
3031 resp_off = static_cast<uint16_t>(resp_off + 4u);
3032 done = static_cast<uint16_t>(i + 1u);
3033 }
3034
3035 Memory::FastCopy(&resp[1], &done, sizeof(done));
3036 resp[3] = xresp;
3037 out_len = resp_off;
3038 return ErrorCode::OK;
3039}
3040
3041template <typename SwdPort>
3042ErrorCode DapLinkV1Class<SwdPort>::HandleJtagWriteAbort(bool /*in_isr*/,
3043 const uint8_t* req,
3044 uint16_t req_len, uint8_t* resp,
3045 uint16_t resp_cap,
3046 uint16_t& out_len)
3047{
3048 if (!resp || resp_cap < 2u)
3049 {
3050 out_len = 0u;
3051 return ErrorCode::ARG_ERR;
3052 }
3053
3054 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT);
3055 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
3056 out_len = 2u;
3057
3058 if (!req || req_len < 6u || jtag_ == nullptr || jtag_chain_.count == 0u)
3059 {
3060 return ErrorCode::ARG_ERR;
3061 }
3062
3063 const uint8_t TAP_INDEX = req[1];
3064 if (TAP_INDEX >= jtag_chain_.count)
3065 {
3066 return ErrorCode::OK;
3067 }
3068
3069 jtag_chain_.index = TAP_INDEX;
3070 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
3071
3072 uint32_t flags = 0u;
3073 Memory::FastCopy(&flags, &req[2], sizeof(flags));
3074
3075 LibXR::Debug::JtagDp dp(*jtag_, &jtag_chain_);
3076 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
3077 const ErrorCode EC = dp.WriteAbort(flags, ack);
3078 const uint8_t V = MapAckToDapResp(ack);
3079
3080 if (EC == ErrorCode::OK && V == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
3081 {
3082 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
3083 }
3084
3085 return ErrorCode::OK;
3086}
3087
3088template <typename SwdPort>
3089void DapLinkV1Class<SwdPort>::DriveReset(bool release)
3090{
3091 last_nreset_level_high_ = release;
3092
3093 if (release)
3094 {
3095 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
3096 }
3097 else
3098 {
3099 swj_shadow_ = static_cast<uint8_t>(
3100 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
3101 }
3102
3103 if (nreset_gpio_ != nullptr)
3104 {
3105 (void)nreset_gpio_->Write(release);
3106 }
3107}
3108
3109template <typename SwdPort>
3110void DapLinkV1Class<SwdPort>::DelayUsIfAllowed(bool /*in_isr*/, uint32_t us)
3111{
3113}
3114
3115} // namespace LibXR::USB
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:143
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:166
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
JTAG-DP 事务层封装(DP/AP 访问与 IDCODE/ABORT)。
Definition jtag_dp.hpp:20
Abstract JTAG base class providing TAP control and IR/DR shifting.
Definition jtag.hpp:37
virtual void Close()=0
Close JTAG and release resources.
virtual ErrorCode Sequence(uint32_t cycles, bool tms, const uint8_t *tdi_lsb_first, uint8_t *tdo_lsb_first)=0
Shift a fixed-TMS sequence, LSB first.
virtual ErrorCode SetClockHz(uint32_t hz)=0
Set TCK frequency, if supported.
virtual void IdleClocks(uint32_t cycles)=0
Insert idle clock cycles in Run-Test/Idle.
通用输入输出(GPIO)接口类。General Purpose Input/Output (GPIO) interface class.
Definition gpio.hpp:13
virtual bool Read()=0
读取 GPIO 引脚状态。Reads the GPIO pin state.
virtual void Write(bool value)=0
写入 GPIO 引脚状态。Writes the GPIO pin state.
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
static void DelayMicroseconds(uint32_t us)
微秒级延时 / Delay in microseconds
Definition timebase.hpp:65
USB描述符基类 USB descriptor base class.
Definition desc_dev.hpp:39
Data data_
设备描述符数据实例 / Internal data instance
Definition desc_dev.hpp:108
@ HID
人机接口类 / Human Interface Device
EPNumber
端点号 Endpoint number
Definition ep.hpp:42
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
void SetActiveLength(uint16_t len)
设置当前活动缓冲区有效长度 / Set active buffer valid length
Definition ep.hpp:270
virtual size_t MaxTransferSize() const
返回当前最大可传输字节数 / Return maximum transferable size at this time
Definition ep.hpp:282
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
Definition ep.hpp:261
virtual void Configure(const Config &cfg)=0
配置端点协议参数 / Configure endpoint protocol parameters
@ INTERRUPT
中断端点 / Interrupt
size_t GetActiveLength()
获取当前活动缓冲区有效长度 / Get active buffer valid length
Definition ep.hpp:276
State GetState() const
获取端点状态 / Get endpoint state
Definition ep.hpp:207
virtual ErrorCode Transfer(size_t size)=0
启动一次传输 / Start a transfer
RawData GetBuffer() const
获取当前可用于传输的缓冲区 / Get current transfer buffer
Definition ep.hpp:245
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:29
USB HID(Human Interface Device)基类,支持可选 OUT 端点、自动生成描述符,适合键盘、鼠标、手柄等扩展。 USB HID (Human Interface Device)...
Definition hid.hpp:24
void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化 HID 设备 Deinitialize HID device.
Definition hid.hpp:267
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool) override
初始化 HID 设备,自动选择端点与描述符块 Initialize HID device and select descriptor block (IN or IN+OUT).
Definition hid.hpp:145
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
JTAG 设备链配置 / JTAG device chain configuration.
uint8_t count
设备数(TDO 端为 index=0)/ Device count (TDO side index=0)
uint32_t ir_before_bits_len
前面设备 IR 总位数 / IR bits before
uint32_t ir_after_bits_len
后面设备 IR 总位数 / IR bits after
uint32_t dr_after_bits_len
后面设备 DR 总位数 / DR bits after
uint8_t index
当前设备索引 / Current device index
uint32_t dr_before_bits_len
前面设备 DR 总位数 / DR bits before
传输策略(WAIT 重试与空闲周期插入)。Transfer policy (WAIT retry & idle insertion).
Definition swd.hpp:31
uint8_t idle_cycles
空闲周期数。Idle cycles.
Definition swd.hpp:32
uint16_t wait_retry
WAIT 最大重试次数。Maximum WAIT retries.
Definition swd.hpp:33
ClassID bDeviceClass
设备类代码 / Device class code
Definition desc_dev.hpp:92
uint8_t bDeviceSubClass
设备子类代码 / Device subclass code
Definition desc_dev.hpp:93
uint8_t bDeviceProtocol
协议代码 / Protocol code
Definition desc_dev.hpp:94