7#include "daplink_v1_def.hpp"
8#include "debug/swd.hpp"
11#include "libxr_def.hpp"
12#include "libxr_mem.hpp"
13#include "libxr_type.hpp"
14#include "timebase.hpp"
19static constexpr uint8_t DAPLINK_V1_REPORT_DESC[] = {
38template <
typename SwdPort>
40 :
public HID<sizeof(DAPLINK_V1_REPORT_DESC), DapLinkV1Def::MAX_REQUEST_SIZE,
41 DapLinkV1Def::MAX_RESPONSE_SIZE>
46 const char* vendor =
nullptr;
47 const char* product =
nullptr;
48 const char* serial =
nullptr;
49 const char* firmware_ver =
nullptr;
51 const char* device_vendor =
nullptr;
52 const char* device_name =
nullptr;
53 const char* board_vendor =
nullptr;
54 const char* board_name =
nullptr;
55 const char* product_fw_ver =
nullptr;
69 bool IsInited()
const;
76 bool in_isr)
override;
88 static void OnDataOutCompleteStatic(
bool in_isr,
DapLinkV1Class* self,
90 static void OnDataInCompleteStatic(
bool in_isr,
DapLinkV1Class* self,
93 uint16_t GetDapPacketSize()
const;
94 uint16_t ClipResponseLength(uint16_t len, uint16_t cap)
const;
95 static constexpr uint8_t NextRespQueueIndex(uint8_t idx);
96 void ResetResponseQueue();
97 bool HasDeferredResponseInEpBuffer()
const;
98 void SetDeferredResponseInEpBuffer(uint16_t len);
99 bool SubmitDeferredResponseIfIdle();
100 bool IsResponseQueueEmpty()
const;
101 bool IsResponseQueueFull()
const;
102 bool TryBuildAndEnqueueResponse(
bool in_isr,
const uint8_t* req, uint16_t req_len);
103 uint8_t OutstandingResponseCount()
const;
104 bool EnqueueResponse(
const uint8_t* data, uint16_t len);
105 bool SubmitNextQueuedResponseIfIdle();
106 void ArmOutTransferIfIdle();
107 uint16_t PrepareResponseReport(uint8_t* resp, uint16_t payload_len, uint16_t cap);
108 void UpdateControlInputReport(
const uint8_t* resp, uint16_t len);
109 ErrorCode HandleControlReportRequest(
bool in_isr,
const uint8_t* req, uint16_t req_len);
110 void HandleHostRequest(
bool in_isr,
const uint8_t* req, uint16_t req_len);
112 ErrorCode ProcessOneCommand(
bool in_isr,
const uint8_t* req, uint16_t req_len,
113 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
114 void BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
116 ErrorCode HandleInfo(
bool in_isr,
const uint8_t* req, uint16_t req_len, uint8_t* resp,
117 uint16_t resp_cap, uint16_t& out_len);
118 ErrorCode HandleHostStatus(
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 HandleConnect(
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 HandleDisconnect(
bool in_isr,
const uint8_t* req, uint16_t req_len,
123 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
124 ErrorCode HandleTransferConfigure(
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 HandleTransfer(
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 HandleTransferBlock(
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 HandleTransferAbort(
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 HandleWriteABORT(
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 HandleDelay(
bool in_isr,
const uint8_t* req, uint16_t req_len, uint8_t* resp,
135 uint16_t resp_cap, uint16_t& out_len);
136 ErrorCode HandleResetTarget(
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 HandleSWJPins(
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 HandleSWJClock(
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 HandleSWJSequence(
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 HandleSWDConfigure(
bool in_isr,
const uint8_t* req, uint16_t req_len,
145 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
146 ErrorCode HandleSWDSequence(
bool in_isr,
const uint8_t* req, uint16_t req_len,
147 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
149 ErrorCode BuildInfoStringResponse(uint8_t cmd,
const char* str, uint8_t* resp,
150 uint16_t resp_cap, uint16_t& out_len);
151 ErrorCode BuildInfoU8Response(uint8_t cmd, uint8_t val, uint8_t* resp,
152 uint16_t resp_cap, uint16_t& out_len);
153 ErrorCode BuildInfoU16Response(uint8_t cmd, uint16_t val, uint8_t* resp,
154 uint16_t resp_cap, uint16_t& out_len);
155 ErrorCode BuildInfoU32Response(uint8_t cmd, uint32_t val, uint8_t* resp,
156 uint16_t resp_cap, uint16_t& out_len);
158 uint8_t MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack)
const;
159 void SetTransferAbortFlag(
bool on);
161 void DriveReset(
bool release);
162 void DelayUsIfAllowed(
bool in_isr, uint32_t us);
165 template <
typename E>
166 static constexpr uint8_t ToU8(E e)
168 return static_cast<uint8_t
>(e);
171 static constexpr uint8_t DAP_OK = 0x00u;
172 static constexpr uint8_t DAP_ERROR = 0xFFu;
174 static inline ErrorCode BuildUnknowCmdResponse(uint8_t* resp, uint16_t cap,
177 if (!resp || cap < 1u)
187 static constexpr uint16_t MAX_REQ = DapLinkV1Def::MAX_REQUEST_SIZE;
188 static constexpr uint16_t MAX_RESP = DapLinkV1Def::MAX_RESPONSE_SIZE;
189 static constexpr uint16_t DEFAULT_DAP_PACKET_SIZE = MAX_RESP;
190 static constexpr uint8_t PACKET_COUNT_ADVERTISED = 1u;
191 static constexpr uint8_t MAX_OUTSTANDING_RESPONSES = PACKET_COUNT_ADVERTISED;
192 static constexpr uint16_t MAX_DAP_PACKET_SIZE = MAX_RESP;
193 static constexpr uint16_t RESP_SLOT_SIZE = MAX_DAP_PACKET_SIZE;
194 static constexpr uint8_t RESP_QUEUE_DEPTH = PACKET_COUNT_ADVERTISED;
195 static_assert(RESP_SLOT_SIZE >= DEFAULT_DAP_PACKET_SIZE,
196 "RESP_SLOT_SIZE must cover HID packet size");
197 static_assert((RESP_QUEUE_DEPTH & (RESP_QUEUE_DEPTH - 1u)) == 0u,
198 "Response queue depth must be power-of-two");
203 uint8_t payload[RESP_SLOT_SIZE] = {};
209 uint8_t swj_shadow_ =
static_cast<uint8_t
>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
210 DapLinkV1Def::DAP_SWJ_NRESET);
211 bool last_nreset_level_high_ =
true;
214 InfoStrings info_{
"XRobot",
"DAPLinkV1",
"00000001",
"1.0.0",
"XRUSB",
215 "XRDAP",
"XRobot",
"DAP_DEMO",
"0.1.0"};
217 uint32_t swj_clock_hz_ = 1000000u;
218 uint32_t match_mask_ = 0xFFFFFFFFu;
220 Endpoint* ep_in_ =
nullptr;
221 Endpoint* ep_out_ =
nullptr;
228 bool inited_ =
false;
229 ResponseSlot resp_q_[RESP_QUEUE_DEPTH] = {};
230 uint8_t resp_q_head_ = 0u;
231 uint8_t resp_q_tail_ = 0u;
232 uint8_t resp_q_count_ = 0u;
233 bool deferred_in_resp_valid_ =
false;
234 uint16_t deferred_in_resp_len_ = 0u;
235 uint8_t control_input_report_[MAX_DAP_PACKET_SIZE] = {};
236 uint16_t control_input_report_len_ = DEFAULT_DAP_PACKET_SIZE;
239template <
typename SwdPort>
240DapLinkV1Class<SwdPort>::DapLinkV1Class(SwdPort& swd_link,
LibXR::GPIO* nreset_gpio,
243 : HID(true, 1, 1, in_ep_num, out_ep_num), swd_(swd_link), nreset_gpio_(nreset_gpio)
245 (void)swd_.SetClockHz(swj_clock_hz_);
248template <
typename SwdPort>
249void DapLinkV1Class<SwdPort>::SetInfoStrings(
const InfoStrings& info)
254template <
typename SwdPort>
260template <
typename SwdPort>
261bool DapLinkV1Class<SwdPort>::IsInited()
const
266template <
typename SwdPort>
275template <
typename SwdPort>
278 return ConstRawData{DAPLINK_V1_REPORT_DESC,
sizeof(DAPLINK_V1_REPORT_DESC)};
281template <
typename SwdPort>
283 uint8_t start_itf_num,
bool in_isr)
290 if (ep_in_ !=
nullptr)
297 if (ep_out_ !=
nullptr)
305 match_mask_ = 0xFFFFFFFFu;
308 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
310 ResetResponseQueue();
311 if (ep_in_ !=
nullptr)
316 swj_clock_hz_ = 1000000u;
317 (void)swd_.SetClockHz(swj_clock_hz_);
319 last_nreset_level_high_ =
true;
320 swj_shadow_ =
static_cast<uint8_t
>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
321 DapLinkV1Def::DAP_SWJ_NRESET);
323 ArmOutTransferIfIdle();
326template <
typename SwdPort>
330 ResetResponseQueue();
332 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
335 if (ep_in_ !=
nullptr)
339 if (ep_out_ !=
nullptr)
351 last_nreset_level_high_ =
true;
352 swj_shadow_ =
static_cast<uint8_t
>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
353 DapLinkV1Def::DAP_SWJ_NRESET);
356template <
typename SwdPort>
360 if (self && self->inited_)
362 self->OnDataOutComplete(in_isr, data);
366template <
typename SwdPort>
367void DapLinkV1Class<SwdPort>::OnDataInCompleteStatic(
bool in_isr, DapLinkV1Class* self,
370 if (self && self->inited_)
372 self->OnDataInComplete(in_isr, data);
376template <
typename SwdPort>
379 if (!inited_ || !ep_in_ || !ep_out_)
384 ArmOutTransferIfIdle();
385 HandleHostRequest(in_isr,
static_cast<const uint8_t*
>(data.
addr_),
386 static_cast<uint16_t
>(data.
size_));
389template <
typename SwdPort>
390void DapLinkV1Class<SwdPort>::OnDataInComplete(
bool ,
393 (void)SubmitDeferredResponseIfIdle();
394 (void)SubmitNextQueuedResponseIfIdle();
395 ArmOutTransferIfIdle();
398template <
typename SwdPort>
401 (void)
HID<
sizeof(DAPLINK_V1_REPORT_DESC), DapLinkV1Def::MAX_REQUEST_SIZE,
403 const auto* req =
static_cast<const uint8_t*
>(data.
addr_);
404 uint16_t req_len =
static_cast<uint16_t
>(data.
size_);
405 return HandleControlReportRequest(in_isr, req, req_len);
408template <
typename SwdPort>
413 if (!req || req_len == 0u)
415 control_input_report_len_ = 0u;
419 uint16_t out_len = 0u;
420 const ErrorCode ANS = ProcessOneCommand(in_isr, req, req_len, control_input_report_,
421 MAX_DAP_PACKET_SIZE, out_len);
423 out_len = ClipResponseLength(out_len, MAX_DAP_PACKET_SIZE);
425 uint16_t tx_len = GetDapPacketSize();
426 if (tx_len == 0u || tx_len > MAX_DAP_PACKET_SIZE)
428 tx_len = MAX_DAP_PACKET_SIZE;
430 if (tx_len < out_len)
434 if (tx_len > out_len)
439 control_input_report_len_ = tx_len;
443template <
typename SwdPort>
447 const uint16_t TX_LEN =
448 (control_input_report_len_ > 0u) ? control_input_report_len_ : GetDapPacketSize();
453template <
typename SwdPort>
457 const uint16_t TX_LEN =
458 (control_input_report_len_ > 0u) ? control_input_report_len_ : GetDapPacketSize();
463template <
typename SwdPort>
465 uint16_t payload_len,
468 if (!resp || cap == 0u)
470 control_input_report_len_ = 0u;
474 payload_len = ClipResponseLength(payload_len, cap);
476 uint16_t tx_len = GetDapPacketSize();
477 if (tx_len == 0u || tx_len > cap)
481 if (tx_len < payload_len)
483 tx_len = payload_len;
485 if (tx_len > payload_len)
490 UpdateControlInputReport(resp, tx_len);
494template <
typename SwdPort>
495void DapLinkV1Class<SwdPort>::UpdateControlInputReport(
const uint8_t* resp, uint16_t len)
499 control_input_report_len_ = 0u;
503 if (len > MAX_DAP_PACKET_SIZE)
505 len = MAX_DAP_PACKET_SIZE;
512 if (len < MAX_DAP_PACKET_SIZE)
514 Memory::FastSet(control_input_report_ + len, 0, MAX_DAP_PACKET_SIZE - len);
517 control_input_report_len_ = len;
520template <
typename SwdPort>
521void DapLinkV1Class<SwdPort>::HandleHostRequest(
bool in_isr,
const uint8_t* req,
524 if (!inited_ || !ep_in_)
529 if (!req || req_len == 0u)
531 ArmOutTransferIfIdle();
535 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
539 if (tx_buff.addr_ && tx_buff.size_ > 0u)
541 auto* tx_buf =
static_cast<uint8_t*
>(tx_buff.addr_);
542 uint16_t out_len = 0u;
543 const auto ANS = ProcessOneCommand(in_isr, req, req_len, tx_buf,
544 static_cast<uint16_t
>(tx_buff.size_), out_len);
547 out_len = ClipResponseLength(out_len,
static_cast<uint16_t
>(tx_buff.size_));
548 const uint16_t TX_LEN =
549 PrepareResponseReport(tx_buf, out_len,
static_cast<uint16_t
>(tx_buff.size_));
555 if (!EnqueueResponse(tx_buf, out_len))
557 (void)SubmitNextQueuedResponseIfIdle();
558 (void)EnqueueResponse(tx_buf, out_len);
561 (void)SubmitNextQueuedResponseIfIdle();
562 ArmOutTransferIfIdle();
567 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
571 if (tx_buff.addr_ && tx_buff.size_ > 0u)
573 auto* tx_buf =
static_cast<uint8_t*
>(tx_buff.addr_);
574 uint16_t out_len = 0u;
575 const auto ANS = ProcessOneCommand(in_isr, req, req_len, tx_buf,
576 static_cast<uint16_t
>(tx_buff.size_), out_len);
579 out_len = ClipResponseLength(out_len,
static_cast<uint16_t
>(tx_buff.size_));
580 const uint16_t TX_LEN =
581 PrepareResponseReport(tx_buf, out_len,
static_cast<uint16_t
>(tx_buff.size_));
582 SetDeferredResponseInEpBuffer(TX_LEN);
583 ArmOutTransferIfIdle();
588 if (TryBuildAndEnqueueResponse(in_isr, req, req_len))
590 (void)SubmitDeferredResponseIfIdle();
591 (void)SubmitNextQueuedResponseIfIdle();
592 ArmOutTransferIfIdle();
596 (void)SubmitNextQueuedResponseIfIdle();
597 (void)TryBuildAndEnqueueResponse(in_isr, req, req_len);
599 (void)SubmitDeferredResponseIfIdle();
600 (void)SubmitNextQueuedResponseIfIdle();
601 ArmOutTransferIfIdle();
604template <
typename SwdPort>
605uint16_t DapLinkV1Class<SwdPort>::GetDapPacketSize()
const
607 const uint16_t IN_PS = ep_in_ ? ep_in_->
MaxPacketSize() : 0u;
608 const uint16_t OUT_PS = ep_out_ ? ep_out_->
MaxPacketSize() : 0u;
609 uint16_t dap_ps = 0u;
611 if (IN_PS > 0u && OUT_PS > 0u)
613 dap_ps = (IN_PS < OUT_PS) ? IN_PS : OUT_PS;
617 dap_ps = (IN_PS > 0u) ? IN_PS : OUT_PS;
622 dap_ps = DEFAULT_DAP_PACKET_SIZE;
624 if (dap_ps > MAX_DAP_PACKET_SIZE)
626 dap_ps = MAX_DAP_PACKET_SIZE;
631template <
typename SwdPort>
632uint16_t DapLinkV1Class<SwdPort>::ClipResponseLength(uint16_t len, uint16_t cap)
const
634 const uint16_t DAP_PS = GetDapPacketSize();
639 if (len > RESP_SLOT_SIZE)
641 len = RESP_SLOT_SIZE;
650template <
typename SwdPort>
651constexpr uint8_t DapLinkV1Class<SwdPort>::NextRespQueueIndex(uint8_t idx)
653 return static_cast<uint8_t
>((idx + 1u) & (RESP_QUEUE_DEPTH - 1u));
656template <
typename SwdPort>
657void DapLinkV1Class<SwdPort>::ResetResponseQueue()
662 deferred_in_resp_valid_ =
false;
663 deferred_in_resp_len_ = 0u;
666template <
typename SwdPort>
667bool DapLinkV1Class<SwdPort>::HasDeferredResponseInEpBuffer()
const
669 return deferred_in_resp_valid_;
672template <
typename SwdPort>
673void DapLinkV1Class<SwdPort>::SetDeferredResponseInEpBuffer(uint16_t len)
675 deferred_in_resp_len_ = len;
676 deferred_in_resp_valid_ =
true;
679template <
typename SwdPort>
680bool DapLinkV1Class<SwdPort>::SubmitDeferredResponseIfIdle()
687 const uint16_t TX_LEN = deferred_in_resp_len_;
693 deferred_in_resp_valid_ =
false;
694 deferred_in_resp_len_ = 0u;
698template <
typename SwdPort>
699bool DapLinkV1Class<SwdPort>::IsResponseQueueEmpty()
const
701 return resp_q_count_ == 0u;
704template <
typename SwdPort>
705bool DapLinkV1Class<SwdPort>::IsResponseQueueFull()
const
707 return resp_q_count_ >= RESP_QUEUE_DEPTH;
710template <
typename SwdPort>
711bool DapLinkV1Class<SwdPort>::TryBuildAndEnqueueResponse(
bool in_isr,
const uint8_t* req,
714 if (!req || IsResponseQueueFull())
719 auto& slot = resp_q_[resp_q_tail_];
720 uint16_t out_len = 0u;
722 ProcessOneCommand(in_isr, req, req_len, slot.payload, RESP_SLOT_SIZE, out_len);
724 slot.len = ClipResponseLength(out_len, RESP_SLOT_SIZE);
725 (void)PrepareResponseReport(slot.payload, slot.len, RESP_SLOT_SIZE);
727 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
732template <
typename SwdPort>
733uint8_t DapLinkV1Class<SwdPort>::OutstandingResponseCount()
const
735 const uint8_t IN_FLIGHT =
737 const uint8_t DEFERRED = deferred_in_resp_valid_ ? 1u : 0u;
738 return static_cast<uint8_t
>(resp_q_count_ + IN_FLIGHT + DEFERRED);
741template <
typename SwdPort>
742bool DapLinkV1Class<SwdPort>::EnqueueResponse(
const uint8_t* data, uint16_t len)
744 if (!data || IsResponseQueueFull())
749 auto& slot = resp_q_[resp_q_tail_];
750 const uint16_t CLIPPED = ClipResponseLength(len, RESP_SLOT_SIZE);
757 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
762template <
typename SwdPort>
763bool DapLinkV1Class<SwdPort>::SubmitNextQueuedResponseIfIdle()
771 if (!tx_buff.addr_ || tx_buff.size_ == 0u)
776 auto& slot = resp_q_[resp_q_head_];
777 uint16_t payload_len = slot.len;
778 if (payload_len > tx_buff.size_)
780 payload_len =
static_cast<uint16_t
>(tx_buff.size_);
783 if (payload_len > 0u)
788 uint16_t tx_len = GetDapPacketSize();
789 if (tx_len == 0u || tx_len > tx_buff.size_)
791 tx_len =
static_cast<uint16_t
>(tx_buff.size_);
793 if (tx_len < payload_len)
795 tx_len = payload_len;
797 if (tx_len > payload_len)
799 Memory::FastSet(
reinterpret_cast<uint8_t*
>(tx_buff.addr_) + payload_len, 0,
800 tx_len - payload_len);
808 resp_q_head_ = NextRespQueueIndex(resp_q_head_);
813template <
typename SwdPort>
814void DapLinkV1Class<SwdPort>::ArmOutTransferIfIdle()
816 if (!inited_ || ep_out_ ==
nullptr || ep_in_ ==
nullptr)
826 if (OutstandingResponseCount() >= MAX_OUTSTANDING_RESPONSES)
832 if (out_rx_len == 0u)
836 (void)ep_out_->
Transfer(out_rx_len);
839template <
typename SwdPort>
840ErrorCode DapLinkV1Class<SwdPort>::ProcessOneCommand(
bool in_isr,
const uint8_t* req,
841 uint16_t req_len, uint8_t* resp,
842 uint16_t resp_cap, uint16_t& out_len)
846 if (!req || !resp || req_len < 1u || resp_cap < 1u)
848 if (resp && resp_cap >= 1u)
850 BuildNotSupportResponse(resp, resp_cap, out_len);
855 const uint8_t CMD = req[0];
859 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::INFO):
860 return HandleInfo(in_isr, req, req_len, resp, resp_cap, out_len);
861 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS):
862 return HandleHostStatus(in_isr, req, req_len, resp, resp_cap, out_len);
863 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT):
864 return HandleConnect(in_isr, req, req_len, resp, resp_cap, out_len);
865 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT):
866 return HandleDisconnect(in_isr, req, req_len, resp, resp_cap, out_len);
867 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE):
868 return HandleTransferConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
869 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER):
870 return HandleTransfer(in_isr, req, req_len, resp, resp_cap, out_len);
871 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK):
872 return HandleTransferBlock(in_isr, req, req_len, resp, resp_cap, out_len);
873 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT):
874 return HandleTransferAbort(in_isr, req, req_len, resp, resp_cap, out_len);
875 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT):
876 return HandleWriteABORT(in_isr, req, req_len, resp, resp_cap, out_len);
877 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::DELAY):
878 return HandleDelay(in_isr, req, req_len, resp, resp_cap, out_len);
879 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET):
880 return HandleResetTarget(in_isr, req, req_len, resp, resp_cap, out_len);
881 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS):
882 return HandleSWJPins(in_isr, req, req_len, resp, resp_cap, out_len);
883 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK):
884 return HandleSWJClock(in_isr, req, req_len, resp, resp_cap, out_len);
885 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE):
886 return HandleSWJSequence(in_isr, req, req_len, resp, resp_cap, out_len);
887 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE):
888 return HandleSWDConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
889 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE):
890 return HandleSWDSequence(in_isr, req, req_len, resp, resp_cap, out_len);
892 (void)BuildUnknowCmdResponse(resp, resp_cap, out_len);
897template <
typename SwdPort>
898void DapLinkV1Class<SwdPort>::BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap,
901 if (!resp || resp_cap < 1u)
910template <
typename SwdPort>
911ErrorCode DapLinkV1Class<SwdPort>::HandleInfo(
bool ,
const uint8_t* req,
912 uint16_t req_len, uint8_t* resp,
913 uint16_t resp_cap, uint16_t& out_len)
917 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
923 const uint8_t INFO_ID = req[1];
925 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
929 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::VENDOR):
930 return BuildInfoStringResponse(resp[0], info_.vendor, resp, resp_cap, out_len);
931 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT):
932 return BuildInfoStringResponse(resp[0], info_.product, resp, resp_cap, out_len);
933 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::SERIAL_NUMBER):
934 return BuildInfoStringResponse(resp[0], info_.serial, resp, resp_cap, out_len);
935 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::FIRMWARE_VERSION):
936 return BuildInfoStringResponse(resp[0], info_.firmware_ver, resp, resp_cap,
938 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_VENDOR):
939 return BuildInfoStringResponse(resp[0], info_.device_vendor, resp, resp_cap,
941 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_NAME):
942 return BuildInfoStringResponse(resp[0], info_.device_name, resp, resp_cap, out_len);
943 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_VENDOR):
944 return BuildInfoStringResponse(resp[0], info_.board_vendor, resp, resp_cap,
946 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_NAME):
947 return BuildInfoStringResponse(resp[0], info_.board_name, resp, resp_cap, out_len);
948 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT_FIRMWARE_VERSION):
949 return BuildInfoStringResponse(resp[0], info_.product_fw_ver, resp, resp_cap,
951 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::CAPABILITIES):
952 return BuildInfoU8Response(resp[0],
LibXR::USB::DapLinkV1Def::DAP_CAP_SWD, resp,
954 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_COUNT):
955 return BuildInfoU8Response(resp[0], PACKET_COUNT_ADVERTISED, resp, resp_cap,
957 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_SIZE):
959 const uint16_t DAP_PS = GetDapPacketSize();
960 return BuildInfoU16Response(resp[0], DAP_PS, resp, resp_cap, out_len);
962 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::TIMESTAMP_CLOCK):
963 return BuildInfoU32Response(resp[0], 1000000U, resp, resp_cap, out_len);
971template <
typename SwdPort>
972ErrorCode DapLinkV1Class<SwdPort>::BuildInfoStringResponse(uint8_t cmd,
const char* str,
986 const size_t N_WITH_NUL = std::strlen(str) + 1;
987 const size_t MAX_PAYLOAD = (resp_cap >= 2u) ? (resp_cap - 2u) : 0u;
988 if (MAX_PAYLOAD == 0u)
994 const size_t COPY_N = (N_WITH_NUL > MAX_PAYLOAD) ? MAX_PAYLOAD : N_WITH_NUL;
996 resp[2 + COPY_N - 1] = 0x00;
997 resp[1] =
static_cast<uint8_t
>(COPY_N);
998 out_len =
static_cast<uint16_t
>(COPY_N + 2u);
1002template <
typename SwdPort>
1003ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU8Response(uint8_t cmd, uint8_t val,
1004 uint8_t* resp, uint16_t resp_cap,
1019template <
typename SwdPort>
1020ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU16Response(uint8_t cmd, uint16_t val,
1021 uint8_t* resp, uint16_t resp_cap,
1036template <
typename SwdPort>
1037ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU32Response(uint8_t cmd, uint32_t val,
1038 uint8_t* resp, uint16_t resp_cap,
1053template <
typename SwdPort>
1054ErrorCode DapLinkV1Class<SwdPort>::HandleHostStatus(
bool ,
1056 uint16_t , uint8_t* resp,
1057 uint16_t resp_cap, uint16_t& out_len)
1064 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS);
1065 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1070template <
typename SwdPort>
1071ErrorCode DapLinkV1Class<SwdPort>::HandleConnect(
bool ,
const uint8_t* req,
1072 uint16_t req_len, uint8_t* resp,
1073 uint16_t resp_cap, uint16_t& out_len)
1081 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT);
1089 if (port == 0u || port == ToU8(LibXR::USB::DapLinkV1Def::Port::SWD))
1091 (void)swd_.EnterSwd();
1092 (void)swd_.SetClockHz(swj_clock_hz_);
1094 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::SWD;
1097 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Port::SWD);
1101 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
1108template <
typename SwdPort>
1109ErrorCode DapLinkV1Class<SwdPort>::HandleDisconnect(
bool ,
1111 uint16_t , uint8_t* resp,
1112 uint16_t resp_cap, uint16_t& out_len)
1121 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
1124 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT);
1125 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1130template <
typename SwdPort>
1131ErrorCode DapLinkV1Class<SwdPort>::HandleTransferConfigure(
1132 bool ,
const uint8_t* req, uint16_t req_len, uint8_t* resp,
1133 uint16_t resp_cap, uint16_t& out_len)
1141 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE);
1145 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1150 const uint8_t IDLE = req[1];
1152 uint16_t wait_retry = 0u;
1153 uint16_t match_retry = 0u;
1164 swd_.SetTransferPolicy(pol);
1166 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1171template <
typename SwdPort>
1172ErrorCode DapLinkV1Class<SwdPort>::HandleTransferAbort(
bool ,
1175 uint8_t* resp, uint16_t resp_cap,
1184 SetTransferAbortFlag(
true);
1186 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT);
1187 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1192template <
typename SwdPort>
1193ErrorCode DapLinkV1Class<SwdPort>::HandleWriteABORT(
bool ,
const uint8_t* req,
1194 uint16_t req_len, uint8_t* resp,
1195 uint16_t resp_cap, uint16_t& out_len)
1203 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT);
1207 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1212 uint32_t flags = 0u;
1215 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1216 const ErrorCode EC = swd_.WriteAbortTxn(flags, ack);
1217 resp[1] = (EC ==
ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1218 ? ToU8(LibXR::USB::DapLinkV1Def::Status::OK)
1219 : ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1225template <
typename SwdPort>
1226ErrorCode DapLinkV1Class<SwdPort>::HandleDelay(
bool ,
const uint8_t* req,
1227 uint16_t req_len, uint8_t* resp,
1228 uint16_t resp_cap, uint16_t& out_len)
1236 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::DELAY);
1240 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1250 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1255template <
typename SwdPort>
1256ErrorCode DapLinkV1Class<SwdPort>::HandleResetTarget(
bool in_isr,
const uint8_t* ,
1257 uint16_t , uint8_t* resp,
1258 uint16_t resp_cap, uint16_t& out_len)
1260 if (!resp || resp_cap < 3u)
1266 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET);
1268 uint8_t execute = 0u;
1269 if (nreset_gpio_ !=
nullptr)
1272 DelayUsIfAllowed(in_isr, 1000u);
1274 DelayUsIfAllowed(in_isr, 1000u);
1284template <
typename SwdPort>
1285ErrorCode DapLinkV1Class<SwdPort>::HandleSWJPins(
bool ,
const uint8_t* req,
1286 uint16_t req_len, uint8_t* resp,
1287 uint16_t resp_cap, uint16_t& out_len)
1289 if (!resp || resp_cap < 2u)
1295 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS);
1297 if (!req || req_len < 7u)
1304 const uint8_t PIN_OUT = req[1];
1305 const uint8_t PIN_SEL = req[2];
1307 uint32_t wait_us = 0u;
1310 swj_shadow_ =
static_cast<uint8_t
>((swj_shadow_ &
static_cast<uint8_t
>(~PIN_SEL)) |
1311 (PIN_OUT & PIN_SEL));
1313 if ((PIN_SEL & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u)
1315 const bool LEVEL_HIGH = ((PIN_OUT & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u);
1316 DriveReset(LEVEL_HIGH);
1319 auto read_pins = [&]() -> uint8_t
1321 uint8_t pin_in = swj_shadow_;
1323 if (nreset_gpio_ !=
nullptr)
1325 if (nreset_gpio_->
Read())
1327 pin_in |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
1331 pin_in =
static_cast<uint8_t
>(
1332 pin_in &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
1339 uint8_t pin_in = 0u;
1340 if (wait_us == 0u || PIN_SEL == 0u)
1342 pin_in = read_pins();
1347 const uint8_t EXPECT =
static_cast<uint8_t
>(PIN_OUT & PIN_SEL);
1351 pin_in = read_pins();
1352 if ((pin_in & PIN_SEL) == EXPECT)
1365template <
typename SwdPort>
1366ErrorCode DapLinkV1Class<SwdPort>::HandleSWJClock(
bool ,
const uint8_t* req,
1367 uint16_t req_len, uint8_t* resp,
1368 uint16_t resp_cap, uint16_t& out_len)
1376 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK);
1380 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1389 (void)swd_.SetClockHz(hz);
1391 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1396template <
typename SwdPort>
1397ErrorCode DapLinkV1Class<SwdPort>::HandleSWJSequence(
bool ,
const uint8_t* req,
1398 uint16_t req_len, uint8_t* resp,
1399 uint16_t resp_cap, uint16_t& out_len)
1401 if (!resp || resp_cap < 2u)
1407 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE);
1408 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1411 if (!req || req_len < 2u)
1413 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1417 uint32_t bit_count = req[1];
1418 if (bit_count == 0u)
1423 const uint32_t BYTE_COUNT = (bit_count + 7u) / 8u;
1424 if (req_len < (2u + BYTE_COUNT))
1426 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1430 const uint8_t* data = &req[2];
1431 const ErrorCode EC = swd_.SeqWriteBits(bit_count, data);
1434 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1438 swj_shadow_ =
static_cast<uint8_t
>(
1439 swj_shadow_ &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWCLK_TCK));
1441 bool last_swdio =
false;
1442 if (bit_count != 0u)
1444 const uint32_t LAST_I = bit_count - 1u;
1445 last_swdio = (((data[LAST_I / 8u] >> (LAST_I & 7u)) & 0x01u) != 0u);
1450 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS;
1454 swj_shadow_ =
static_cast<uint8_t
>(
1455 swj_shadow_ &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS));
1461template <
typename SwdPort>
1462ErrorCode DapLinkV1Class<SwdPort>::HandleSWDConfigure(
bool ,
1464 uint16_t , uint8_t* resp,
1474 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE);
1475 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1480template <
typename SwdPort>
1481ErrorCode DapLinkV1Class<SwdPort>::HandleSWDSequence(
bool ,
const uint8_t* req,
1482 uint16_t req_len, uint8_t* resp,
1483 uint16_t resp_cap, uint16_t& out_len)
1485 if (!req || !resp || resp_cap < 2u)
1491 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE);
1497 resp[1] = DAP_ERROR;
1502 const uint8_t SEQ_CNT = req[1];
1503 uint16_t req_off = 2u;
1504 uint16_t resp_off = 2u;
1506 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1508 if (req_off >= req_len)
1510 resp[1] = DAP_ERROR;
1515 const uint8_t INFO = req[req_off++];
1516 uint32_t cycles =
static_cast<uint32_t
>(INFO & 0x3Fu);
1522 const bool MODE_IN = ((INFO & 0x80u) != 0u);
1523 const uint16_t BYTES =
static_cast<uint16_t
>((cycles + 7u) / 8u);
1527 if (req_off + BYTES > req_len)
1529 resp[1] = DAP_ERROR;
1534 const uint8_t* data = &req[req_off];
1535 req_off =
static_cast<uint16_t
>(req_off + BYTES);
1537 const ErrorCode EC = swd_.SeqWriteBits(cycles, data);
1540 resp[1] = DAP_ERROR;
1547 if (resp_off + BYTES > resp_cap)
1549 resp[1] = DAP_ERROR;
1555 const ErrorCode EC = swd_.SeqReadBits(cycles, &resp[resp_off]);
1558 resp[1] = DAP_ERROR;
1563 resp_off =
static_cast<uint16_t
>(resp_off + BYTES);
1571template <
typename SwdPort>
1572uint8_t DapLinkV1Class<SwdPort>::MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack)
const
1576 case LibXR::Debug::SwdProtocol::Ack::OK:
1578 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1580 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1582 case LibXR::Debug::SwdProtocol::Ack::NO_ACK:
1583 case LibXR::Debug::SwdProtocol::Ack::PROTOCOL:
1589template <
typename SwdPort>
1590void DapLinkV1Class<SwdPort>::SetTransferAbortFlag(
bool on)
1595template <
typename SwdPort>
1596ErrorCode DapLinkV1Class<SwdPort>::HandleTransfer(
bool ,
const uint8_t* req,
1597 uint16_t req_len, uint8_t* resp,
1598 uint16_t resp_cap, uint16_t& out_len)
1601 if (!req || !resp || resp_cap < 3u)
1606 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER);
1609 uint16_t resp_off = 3u;
1613 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1621 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1626 const uint8_t COUNT = req[2];
1627 uint16_t req_off = 3u;
1629 auto ack_to_dap = [&](LibXR::Debug::SwdProtocol::Ack ack) -> uint8_t
1633 case LibXR::Debug::SwdProtocol::Ack::OK:
1634 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1635 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1636 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_WAIT;
1637 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1638 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_FAULT;
1644 auto push_u32 = [&](uint32_t VALUE) ->
bool
1646 if (resp_off + 4u > resp_cap)
1651 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
1655 auto push_timestamp = [&]() ->
bool
1661 auto ensure_space = [&](uint16_t bytes) ->
bool
1662 {
return (resp_off + bytes) <= resp_cap; };
1664 auto bytes_for_read = [&](
bool need_ts) -> uint16_t
1665 {
return static_cast<uint16_t
>(need_ts ? 8u : 4u); };
1667 uint8_t response_count = 0u;
1668 uint8_t response_value = 0u;
1669 bool check_write =
false;
1671 struct PendingApRead
1674 bool need_ts =
false;
1677 auto emit_read_with_ts = [&](
bool need_ts, uint32_t data) ->
bool
1681 if (!push_timestamp())
1686 if (!push_u32(data))
1694 auto complete_pending_by_rdbuff = [&]() ->
bool
1701 if (!ensure_space(bytes_for_read(pending.need_ts)))
1703 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1707 uint32_t rdata = 0u;
1708 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1709 const ErrorCode EC = swd_.DpReadRdbuffTxn(rdata, ack);
1711 const uint8_t V = ack_to_dap(ack);
1712 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1719 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1723 if (!emit_read_with_ts(pending.need_ts, rdata))
1725 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1729 pending.valid =
false;
1730 pending.need_ts =
false;
1731 check_write =
false;
1732 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1736 auto flush_pending_if_any = [&]() ->
bool
1737 {
return pending.valid ? complete_pending_by_rdbuff() : true; };
1739 for (uint32_t i = 0; i < COUNT; ++i)
1741 if (req_off >= req_len)
1743 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1747 const uint8_t RQ = req[req_off++];
1754 const bool MATCH_VALUE =
1755 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
1756 const bool MATCH_MASK =
1757 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK) != 0u);
1759 if (TS && (MATCH_VALUE || MATCH_MASK))
1761 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1765 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1770 if (!flush_pending_if_any())
1775 if (req_off + 4u > req_len)
1777 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1781 uint32_t wdata = 0u;
1783 req_off =
static_cast<uint16_t
>(req_off + 4u);
1787 match_mask_ = wdata;
1788 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1795 ec = swd_.ApWriteTxn(ADDR2B, wdata, ack);
1799 ec = swd_.DpWriteTxn(
static_cast<LibXR::Debug::SwdProtocol::DpWriteReg
>(ADDR2B),
1803 response_value = ack_to_dap(ack);
1804 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1810 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1816 if (!push_timestamp())
1818 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1830 if (!flush_pending_if_any())
1835 if (req_off + 4u > req_len)
1837 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1841 uint32_t match_val = 0u;
1843 req_off =
static_cast<uint16_t
>(req_off + 4u);
1845 uint32_t rdata = 0u;
1847 bool matched =
false;
1853 ec = swd_.ApReadTxn(ADDR2B, rdata, ack);
1854 if (ec ==
ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1856 check_write =
false;
1861 ec = swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
1865 response_value = ack_to_dap(ack);
1866 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1872 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1876 if ((rdata & match_mask_) == (match_val & match_mask_))
1889 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1897 static_cast<uint8_t
>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
1898 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
1902 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1909 if (!flush_pending_if_any())
1914 uint32_t rdata = 0u;
1915 ec = swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
1918 response_value = ack_to_dap(ack);
1919 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1925 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1929 if (!ensure_space(bytes_for_read(TS)))
1931 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1935 if (!emit_read_with_ts(TS, rdata))
1937 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1941 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1947 uint32_t dummy_posted = 0u;
1948 ec = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
1950 response_value = ack_to_dap(ack);
1951 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1957 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1961 pending.valid =
true;
1962 pending.need_ts = TS;
1963 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1967 if (!ensure_space(bytes_for_read(pending.need_ts)))
1969 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1973 uint32_t posted_prev = 0u;
1974 ec = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
1976 const uint8_t CUR_V = ack_to_dap(ack);
1977 if (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK || ec !=
ErrorCode::OK)
1979 const uint8_t PRIOR_FAIL = (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1981 :
LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1983 if (!complete_pending_by_rdbuff())
1988 response_value = PRIOR_FAIL;
1992 if (!emit_read_with_ts(pending.need_ts, posted_prev))
1994 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1998 pending.valid =
true;
1999 pending.need_ts = TS;
2000 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2013 const uint8_t PRIOR_FAIL = response_value;
2015 if (!complete_pending_by_rdbuff())
2020 if (PRIOR_FAIL != 0u && PRIOR_FAIL != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2022 response_value = PRIOR_FAIL;
2027 if (response_value == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK && check_write)
2029 uint32_t dummy = 0u;
2030 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2031 const ErrorCode EC = swd_.DpReadRdbuffTxn(dummy, ack);
2032 const uint8_t V = ack_to_dap(ack);
2034 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2040 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2044 resp[1] = response_count;
2045 resp[2] = response_value;
2050template <
typename SwdPort>
2051ErrorCode DapLinkV1Class<SwdPort>::HandleTransferBlock(
bool ,
2053 uint16_t req_len, uint8_t* resp,
2057 if (!resp || resp_cap < 4u)
2063 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK);
2069 if (!req || req_len < 5u)
2071 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2078 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2082 uint16_t count = 0u;
2085 const uint8_t DAP_RQ = req[4];
2087 if ((DAP_RQ & (LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE |
2088 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
2090 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2095 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2101 const uint16_t DONE0 = 0u;
2103 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2115 uint16_t req_off = 5u;
2116 uint16_t resp_off = 4u;
2120 for (uint32_t i = 0; i < count; ++i)
2122 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2125 if (req_off + 4u > req_len)
2127 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2131 uint32_t wdata = 0u;
2133 req_off =
static_cast<uint16_t
>(req_off + 4u);
2137 ec = swd_.ApWriteTxn(ADDR2B, wdata, ack);
2141 ec = swd_.DpWriteTxn(
static_cast<LibXR::Debug::SwdProtocol::DpWriteReg
>(ADDR2B),
2145 xresp = MapAckToDapResp(ack);
2148 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2152 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2159 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2163 done =
static_cast<uint16_t
>(i + 1u);
2174 for (uint32_t i = 0; i < count; ++i)
2176 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2178 uint32_t rdata = 0u;
2180 if (resp_off + 4u > resp_cap)
2182 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2186 ec = swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
2189 xresp = MapAckToDapResp(ack);
2192 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2196 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2203 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2208 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2209 done =
static_cast<uint16_t
>(i + 1u);
2219 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2222 uint32_t dummy_posted = 0u;
2223 ec = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
2224 xresp = MapAckToDapResp(ack);
2228 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2231 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2237 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2241 for (uint32_t i = 1; i < count; ++i)
2243 if (resp_off + 4u > resp_cap)
2245 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2249 uint32_t posted_prev = 0u;
2250 ec = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
2251 const uint8_t CUR = MapAckToDapResp(ack);
2255 xresp = CUR | LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2259 if (ack != LibXR::Debug::SwdProtocol::Ack::OK || ec !=
ErrorCode::OK)
2261 if (resp_off + 4u <= resp_cap)
2264 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2265 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2266 const uint8_t V2 = MapAckToDapResp(ack2);
2271 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2272 done =
static_cast<uint16_t
>(i);
2279 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2288 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2294 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2295 done =
static_cast<uint16_t
>(i);
2299 if (resp_off + 4u > resp_cap)
2301 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2307 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2308 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2309 const uint8_t V2 = MapAckToDapResp(ack2);
2318 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2323 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2335template <
typename SwdPort>
2336void DapLinkV1Class<SwdPort>::DriveReset(
bool release)
2338 last_nreset_level_high_ = release;
2342 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
2346 swj_shadow_ =
static_cast<uint8_t
>(
2347 swj_shadow_ &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
2350 if (nreset_gpio_ !=
nullptr)
2352 (void)nreset_gpio_->
Write(release);
2356template <
typename SwdPort>
2357void DapLinkV1Class<SwdPort>::DelayUsIfAllowed(
bool , uint32_t us)
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
通用输入输出(GPIO)接口类。General Purpose Input/Output (GPIO) interface class.
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
ErrorCode OnSetReportData(bool in_isr, LibXR::ConstRawData &data) override
处理 SET_REPORT 数据阶段 Handle SET_REPORT data stage
ConstRawData GetReportDesc() override
获取 HID 报告描述符 Get HID Report Descriptor
ErrorCode OnGetInputReport(uint8_t report_id, DeviceClass::ControlTransferResult &result) override
获取输入报告 Get Input Report
void UnbindEndpoints(EndpointPool &endpoint_pool, bool in_isr) override
解绑端点资源 / Unbind endpoint resources
ErrorCode WriteDeviceDescriptor(DeviceDescriptor &header) override
可选:覆盖设备描述符字段 / Optional: override device descriptor fields
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool in_isr) override
绑定端点资源 / Bind endpoint resources
ErrorCode OnGetFeatureReport(uint8_t report_id, DeviceClass::ControlTransferResult &result) override
获取特征报告 Get Feature Report
USB描述符基类 USB descriptor base class.
Data data_
设备描述符数据实例 / Internal data instance
@ PER_INTERFACE
每个接口自定义类 / Per-interface
EPNumber
端点号 Endpoint number
@ EP_AUTO
自动分配端点号 / Auto allocate
@ OUT
输出方向 / OUT direction
void SetActiveLength(uint16_t len)
设置当前活动缓冲区有效长度 / Set active buffer valid length
virtual size_t MaxTransferSize() const
返回当前最大可传输字节数 / Return maximum transferable size at this time
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
virtual void Configure(const Config &cfg)=0
配置端点协议参数 / Configure endpoint protocol parameters
@ INTERRUPT
中断端点 / Interrupt
uint16_t MaxPacketSize() const
获取最大包长 / Get max packet size
State GetState() const
获取端点状态 / Get endpoint state
virtual ErrorCode Transfer(size_t size)=0
启动一次传输 / Start a transfer
RawData GetBuffer() const
获取当前可用于传输的缓冲区 / Get current transfer buffer
USB端点池类 / USB endpoint pool class.
USB HID(Human Interface Device)基类,支持可选 OUT 端点、自动生成描述符,适合键盘、鼠标、手柄等扩展。 USB HID (Human Interface Device)...
void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化 HID 设备 Deinitialize HID device.
Endpoint * GetOutEndpoint()
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool) override
初始化 HID 设备,自动选择端点与描述符块 Initialize HID device and select descriptor block (IN or IN+OUT).
Endpoint * GetInEndpoint()
static constexpr bool req_is_read(std::uint8_t req)
判断是否为读操作。Check if request is read (RnW=1).
static constexpr std::uint8_t req_addr2b(std::uint8_t req)
static constexpr bool req_is_ap(std::uint8_t req)
判断是否为 AP 访问。Check if request targets AP.
static constexpr bool req_need_timestamp(std::uint8_t req)
判断是否需要 timestamp。Check if request needs timestamp.
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
传输策略(WAIT 重试与空闲周期插入)。Transfer policy (WAIT retry & idle insertion).
uint8_t idle_cycles
空闲周期数。Idle cycles.
uint16_t wait_retry
WAIT 最大重试次数。Maximum WAIT retries.
volatile bool transfer_abort
传输中止标志。Transfer abort flag.
DebugPort debug_port
当前调试端口。Current debug port.
TransferConfig transfer_cfg
Transfer 配置。Transfer configuration.
std::uint16_t retry_count
WAIT 重试次数。WAIT retry count.
std::uint8_t idle_cycles
空闲时钟插入。Idle cycles insertion.
std::uint16_t match_retry
MATCH 重试次数。MATCH retry count.
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
ClassID bDeviceClass
设备类代码 / Device class code
uint8_t bDeviceSubClass
设备子类代码 / Device subclass code
uint8_t bDeviceProtocol
协议代码 / Protocol code