libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
daplink_v2.hpp
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <cstring>
6
7#include "daplink_v2_def.hpp"
8#include "debug/swd.hpp"
9#include "dev_core.hpp"
10#include "gpio.hpp"
11#include "libxr_def.hpp"
12#include "libxr_type.hpp"
13#include "timebase.hpp"
14#include "usb/core/desc_cfg.hpp"
15#include "winusb_msos20.hpp"
16
17namespace LibXR::USB
18{
25template <typename SwdPort>
27{
28 public:
33 {
34 const char* vendor = nullptr;
35 const char* product = nullptr;
36 const char* serial = nullptr;
37 const char* firmware_ver = nullptr;
38
39 const char* device_vendor = nullptr;
40 const char* device_name = nullptr;
41 const char* board_vendor = nullptr;
42 const char* board_name = nullptr;
43 const char* product_fw_ver = nullptr;
44 };
45
46 public:
57 SwdPort& swd_link, LibXR::GPIO* nreset_gpio = nullptr,
61 swd_(swd_link),
62 nreset_gpio_(nreset_gpio),
63 data_in_ep_num_(data_in_ep_num),
64 data_out_ep_num_(data_out_ep_num)
65 {
66 (void)swd_.SetClockHz(swj_clock_hz_);
67
68 // Init WinUSB descriptor templates (constant parts)
69 InitWinUsbDescriptors();
70 }
71
75 ~DapLinkV2Class() override = default;
76
77 DapLinkV2Class(const DapLinkV2Class&) = delete;
78 DapLinkV2Class& operator=(const DapLinkV2Class&) = delete;
79
80 public:
85 void SetInfoStrings(const InfoStrings& info) { info_ = info; }
86
92
97 bool IsInited() const { return inited_; }
98
105 bool EpInBusy()
106 {
107 auto ep = ep_data_in_;
108 return ep->GetState() != Endpoint::State::IDLE;
109 }
110
118 {
119 auto ep = ep_data_out_;
120 return ep->GetState() != Endpoint::State::IDLE;
121 }
122
123 protected:
130 void BindEndpoints(EndpointPool& endpoint_pool, uint8_t start_itf_num, bool) override
131 {
132 inited_ = false;
133
134 interface_num_ = start_itf_num;
135
136 // Patch WinUSB function subset to match this interface number
137 UpdateWinUsbInterfaceFields();
138
139 // Allocate endpoints
140 auto ans =
142 ASSERT(ans == ErrorCode::OK);
143
145 ASSERT(ans == ErrorCode::OK);
146
147 // Configure endpoints
148 // - Use upper bound; core will choose a valid max packet size <= this limit.
149 // - Enable double_buffer for USB pipeline overlap.
153 {Endpoint::Direction::IN, Endpoint::Type::BULK, UINT16_MAX, true});
154
155 // Hook callbacks
158
159 // Interface descriptor (vendor specific, 2 endpoints)
160 desc_block_.intf = {9,
161 static_cast<uint8_t>(DescriptorType::INTERFACE),
163 0,
164 2,
165 0xFF, // vendor specific
166 0x00,
167 0x00,
168 0};
169
170 desc_block_.ep_out = {7,
171 static_cast<uint8_t>(DescriptorType::ENDPOINT),
172 static_cast<uint8_t>(ep_data_out_->GetAddress()),
173 static_cast<uint8_t>(Endpoint::Type::BULK),
175 0};
176
177 desc_block_.ep_in = {7,
178 static_cast<uint8_t>(DescriptorType::ENDPOINT),
179 static_cast<uint8_t>(ep_data_in_->GetAddress()),
180 static_cast<uint8_t>(Endpoint::Type::BULK),
182 0};
183
184 SetData(RawData{reinterpret_cast<uint8_t*>(&desc_block_), sizeof(desc_block_)});
185
186 // Runtime defaults
187 dap_state_ = {};
188 dap_state_.debug_port = LibXR::USB::DapLinkV2Def::DebugPort::DISABLED;
190
191 swj_clock_hz_ = 1'000'000u;
192 (void)swd_.SetClockHz(swj_clock_hz_);
193
194 // SWJ shadow defaults: SWDIO=1, nRESET=1, SWCLK=0
196 swj_shadow_ = static_cast<uint8_t>(DapLinkV2Def::DAP_SWJ_SWDIO_TMS |
197 DapLinkV2Def::DAP_SWJ_NRESET);
198
199 ResetResponseQueue();
201
202 inited_ = true;
203 ArmOutTransferIfIdle();
204 }
205
211 void UnbindEndpoints(EndpointPool& endpoint_pool, bool) override
212 {
213 inited_ = false;
214 ResetResponseQueue();
215
216 dap_state_.debug_port = LibXR::USB::DapLinkV2Def::DebugPort::DISABLED;
218
219 if (ep_data_in_)
220 {
223 endpoint_pool.Release(ep_data_in_);
224 ep_data_in_ = nullptr;
225 }
226
227 if (ep_data_out_)
228 {
231 endpoint_pool.Release(ep_data_out_);
232 ep_data_out_ = nullptr;
233 }
234
235 swd_.Close();
236
237 // Reset shadow defaults
239 swj_shadow_ = static_cast<uint8_t>(DapLinkV2Def::DAP_SWJ_SWDIO_TMS |
240 DapLinkV2Def::DAP_SWJ_NRESET);
241 }
242
247 size_t GetInterfaceCount() override { return 1; }
248
253 bool HasIAD() override { return false; }
254
260 bool OwnsEndpoint(uint8_t ep_addr) const override
261 {
262 if (!inited_)
263 {
264 return false;
265 }
266 return (ep_data_in_ && ep_addr == ep_data_in_->GetAddress()) ||
267 (ep_data_out_ && ep_addr == ep_data_out_->GetAddress());
268 }
269
274 size_t GetMaxConfigSize() override { return sizeof(desc_block_); }
275
281 {
282 return ConstRawData{reinterpret_cast<const uint8_t*>(&winusb_msos20_),
283 sizeof(winusb_msos20_)};
284 }
285
290 size_t GetBosCapabilityCount() override { return 1; }
291
297 BosCapability* GetBosCapability(size_t index) override
298 {
299 if (index == 0)
300 {
301 return &winusb_msos20_cap_;
302 }
303 return nullptr;
304 }
305
306 private:
307 // ============================================================================
308 // Local helpers (kept with original comments, moved inside the class)
309 // ============================================================================
310
311 // 枚举/整型转 uint8_t。Cast enum/integer to uint8_t.
312 template <typename E>
313 static constexpr uint8_t ToU8(E e)
314 {
315 return static_cast<uint8_t>(e);
316 }
317
318 // CMSIS-DAP status bytes
319 static constexpr uint8_t DAP_OK = 0x00u;
320 static constexpr uint8_t DAP_ERROR = 0xFFu;
321
322 // 未知命令响应:单字节 0xFF。Unknown command response: single byte 0xFF.
323 static inline ErrorCode BuildUnknowCmdResponse(uint8_t* resp, uint16_t cap,
324 uint16_t& out_len)
325 {
326 if (!resp || cap < 1u)
327 {
328 out_len = 0u;
329 return ErrorCode::NOT_FOUND;
330 }
331 resp[0] = 0xFFu;
332 out_len = 1u;
333 return ErrorCode::OK;
334 }
335
336 // 命令状态响应:<cmd, status>。Command status response: <cmd, status>.
337 static inline ErrorCode BuildCmdStatusResponse(uint8_t cmd, uint8_t status,
338 uint8_t* resp, uint16_t cap,
339 uint16_t& out_len)
340 {
341 if (!resp || cap < 2u)
342 {
343 out_len = 0u;
344 return ErrorCode::NOT_FOUND;
345 }
346 resp[0] = cmd;
347 resp[1] = status;
348 out_len = 2u;
349 return ErrorCode::OK;
350 }
351
352 private:
353 // ============================================================================
354 // WinUSB descriptors
355 // ============================================================================
356
357 void InitWinUsbDescriptors()
358 {
359 winusb_msos20_.set.wLength = static_cast<uint16_t>(sizeof(winusb_msos20_.set));
360 winusb_msos20_.set.wDescriptorType =
361 LibXR::USB::WinUsbMsOs20::MS_OS_20_SET_HEADER_DESCRIPTOR;
362 winusb_msos20_.set.dwWindowsVersion = 0x06030000; // Win 8.1+
363 winusb_msos20_.set.wTotalLength = static_cast<uint16_t>(sizeof(winusb_msos20_));
364
365 winusb_msos20_.cfg.wLength = static_cast<uint16_t>(sizeof(winusb_msos20_.cfg));
366 winusb_msos20_.cfg.wDescriptorType =
367 LibXR::USB::WinUsbMsOs20::MS_OS_20_SUBSET_HEADER_CONFIGURATION;
368
369 winusb_msos20_.cfg.bConfigurationValue = 0;
370 winusb_msos20_.cfg.bReserved = 0;
371 winusb_msos20_.cfg.wTotalLength = static_cast<uint16_t>(
372 sizeof(winusb_msos20_) - offsetof(WinUsbMsOs20DescSet, cfg));
373
374 winusb_msos20_.func.wLength = static_cast<uint16_t>(sizeof(winusb_msos20_.func));
375 winusb_msos20_.func.wDescriptorType =
376 LibXR::USB::WinUsbMsOs20::MS_OS_20_SUBSET_HEADER_FUNCTION;
377 winusb_msos20_.func.bReserved = 0;
378 winusb_msos20_.func.wTotalLength = static_cast<uint16_t>(
379 sizeof(winusb_msos20_) - offsetof(WinUsbMsOs20DescSet, func));
380
381 winusb_msos20_.compat.wLength = static_cast<uint16_t>(sizeof(winusb_msos20_.compat));
382 winusb_msos20_.compat.wDescriptorType =
383 LibXR::USB::WinUsbMsOs20::MS_OS_20_FEATURE_COMPATIBLE_ID;
384
385 winusb_msos20_.prop.header.wDescriptorType =
386 LibXR::USB::WinUsbMsOs20::MS_OS_20_FEATURE_REG_PROPERTY;
387 winusb_msos20_.prop.header.wPropertyDataType = LibXR::USB::WinUsbMsOs20::REG_MULTI_SZ;
388 winusb_msos20_.prop.header.wPropertyNameLength =
389 LibXR::USB::WinUsbMsOs20::PROP_NAME_DEVICE_INTERFACE_GUIDS_BYTES;
390
391 Memory::FastCopy(winusb_msos20_.prop.name,
392 LibXR::USB::WinUsbMsOs20::PROP_NAME_DEVICE_INTERFACE_GUIDS_UTF16,
393 LibXR::USB::WinUsbMsOs20::PROP_NAME_DEVICE_INTERFACE_GUIDS_BYTES);
394
395 // DeviceInterfaceGUIDs: REG_MULTI_SZ UTF-16LE, include double-NUL terminator
396 // 注意:此处为“单 GUID + 双 NUL 结束”的 REG_MULTI_SZ / Single GUID + double-NUL end.
397 const char GUID_STR[] = "{CDB3B5AD-293B-4663-AA36-1AAE46463776}";
398 const size_t GUID_LEN = sizeof(GUID_STR) - 1;
399
400 for (size_t i = 0; i < GUID_LEN; ++i)
401 {
402 winusb_msos20_.prop.data[i * 2] = static_cast<uint8_t>(GUID_STR[i]);
403 winusb_msos20_.prop.data[i * 2 + 1] = 0x00;
404 }
405
406 // Append UTF-16 NUL + extra UTF-16 NUL (REG_MULTI_SZ end)
407 winusb_msos20_.prop.data[GUID_LEN * 2 + 0] = 0x00;
408 winusb_msos20_.prop.data[GUID_LEN * 2 + 1] = 0x00;
409 winusb_msos20_.prop.data[GUID_LEN * 2 + 2] = 0x00;
410 winusb_msos20_.prop.data[GUID_LEN * 2 + 3] = 0x00;
411
412 winusb_msos20_.prop.wPropertyDataLength = static_cast<uint16_t>((GUID_LEN * 2) + 4);
413 winusb_msos20_.prop.header.wLength =
414 static_cast<uint16_t>(sizeof(winusb_msos20_.prop));
415
416 // Sync to BOS capability object
419 }
420
421 void UpdateWinUsbInterfaceFields()
422 {
423 // Function subset interface number
424 winusb_msos20_.func.bFirstInterface = interface_num_;
425
426 // 内容变化但总长度不变;同步一次保持一致性
427 // Content changes but total size stays the same; resync for consistency.
429 }
430
431 private:
432 // ============================================================================
433 // USB callbacks
434 // ============================================================================
435
439 static void OnDataOutCompleteStatic(bool in_isr, DapLinkV2Class* self,
441 {
442 if (self && self->inited_)
443 {
444 self->OnDataOutComplete(in_isr, data);
445 }
446 }
447
451 static void OnDataInCompleteStatic(bool in_isr, DapLinkV2Class* self,
453 {
454 if (self && self->inited_)
455 {
456 self->OnDataInComplete(in_isr, data);
457 }
458 }
459
463 void OnDataOutComplete(bool in_isr, LibXR::ConstRawData& data)
464 {
465 (void)in_isr;
466
467 if (!inited_ || !ep_data_in_ || !ep_data_out_)
468 {
469 return;
470 }
471
472 // 尽早 re-arm OUT 以覆盖 host->probe 流水 / Re-arm OUT early for host->probe overlap.
473 ArmOutTransferIfIdle();
474
475 const auto* req = static_cast<const uint8_t*>(data.addr_);
476 const uint16_t REQ_LEN = static_cast<uint16_t>(data.size_);
477
478 // 快路径:IN idle 且无积压时,直接在 IN 缓冲构造并发送 / Fast path: build directly
479 // in IN endpoint buffer and submit without extra response copy.
480 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
482 {
483 auto tx_buff = ep_data_in_->GetBuffer();
484 if (tx_buff.addr_ && tx_buff.size_ > 0u)
485 {
486 auto* tx_buf = static_cast<uint8_t*>(tx_buff.addr_);
487 uint16_t out_len = 0u;
488 auto ans = ProcessOneCommand(in_isr, req, REQ_LEN, tx_buf,
489 static_cast<uint16_t>(tx_buff.size_), out_len);
490 UNUSED(ans);
491
492 out_len = ClipResponseLength(out_len, static_cast<uint16_t>(tx_buff.size_));
493 if (ep_data_in_->Transfer(out_len) == ErrorCode::OK)
494 {
495 return;
496 }
497
498 if (!EnqueueResponse(tx_buf, out_len))
499 {
500 (void)SubmitNextQueuedResponseIfIdle();
501 (void)EnqueueResponse(tx_buf, out_len);
502 }
503
504 (void)SubmitNextQueuedResponseIfIdle();
505 ArmOutTransferIfIdle();
506 return;
507 }
508 }
509
510 // 延迟快路径:IN busy 且无积压时,直接写入另一半 IN 双缓冲 / Deferred fast path:
511 // build next response in the other IN DB buffer to avoid queue copy.
512 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
514 {
515 auto tx_buff = ep_data_in_->GetBuffer();
516 if (tx_buff.addr_ && tx_buff.size_ > 0u)
517 {
518 auto* tx_buf = static_cast<uint8_t*>(tx_buff.addr_);
519 uint16_t out_len = 0u;
520 auto ans = ProcessOneCommand(in_isr, req, REQ_LEN, tx_buf,
521 static_cast<uint16_t>(tx_buff.size_), out_len);
522 UNUSED(ans);
523
524 out_len = ClipResponseLength(out_len, static_cast<uint16_t>(tx_buff.size_));
525 SetDeferredResponseInEpBuffer(out_len);
526 ArmOutTransferIfIdle();
527 return;
528 }
529 }
530
531 if (TryBuildAndEnqueueResponse(in_isr, req, REQ_LEN))
532 {
533 (void)SubmitDeferredResponseIfIdle();
534 (void)SubmitNextQueuedResponseIfIdle();
535 ArmOutTransferIfIdle();
536 return;
537 }
538
539 // 正常背压下不应触发;这里做一次 best-effort 腾挪后重试队列构建。
540 // Should not happen with proper backpressure; drain once and retry queue build.
541 (void)SubmitNextQueuedResponseIfIdle();
542 (void)TryBuildAndEnqueueResponse(in_isr, req, REQ_LEN);
543
544 (void)SubmitDeferredResponseIfIdle();
545 (void)SubmitNextQueuedResponseIfIdle();
546 ArmOutTransferIfIdle();
547 }
548
552 void OnDataInComplete(bool /*in_isr*/, LibXR::ConstRawData& /*data*/)
553 {
554 (void)SubmitDeferredResponseIfIdle();
555 (void)SubmitNextQueuedResponseIfIdle();
556 ArmOutTransferIfIdle();
557 }
558
559 private:
563 uint16_t GetDapPacketSize() const
564 {
565 const uint16_t IN_PS = ep_data_in_ ? ep_data_in_->MaxPacketSize() : 0u;
566 const uint16_t OUT_PS = ep_data_out_ ? ep_data_out_->MaxPacketSize() : 0u;
567 uint16_t dap_ps = 0u;
568
569 if (IN_PS > 0u && OUT_PS > 0u)
570 {
571 dap_ps = (IN_PS < OUT_PS) ? IN_PS : OUT_PS;
572 }
573 else
574 {
575 dap_ps = (IN_PS > 0u) ? IN_PS : OUT_PS;
576 }
577
578 if (dap_ps == 0u)
579 {
580 dap_ps = DEFAULT_DAP_PACKET_SIZE;
581 }
582 if (dap_ps > MAX_DAP_PACKET_SIZE)
583 {
584 dap_ps = MAX_DAP_PACKET_SIZE;
585 }
586 return dap_ps;
587 }
588
592 uint16_t ClipResponseLength(uint16_t len, uint16_t cap) const
593 {
594 const uint16_t DAP_PS = GetDapPacketSize();
595 if (len > DAP_PS)
596 {
597 len = DAP_PS;
598 }
599 if (len > RESP_SLOT_SIZE)
600 {
601 len = RESP_SLOT_SIZE;
602 }
603 if (len > cap)
604 {
605 len = cap;
606 }
607 return len;
608 }
609
610 static constexpr uint8_t NextRespQueueIndex(uint8_t idx)
611 {
612 return static_cast<uint8_t>((idx + 1u) & (RESP_QUEUE_DEPTH - 1u));
613 }
614
615 void ResetResponseQueue()
616 {
617 resp_q_head_ = 0u;
618 resp_q_tail_ = 0u;
619 resp_q_count_ = 0u;
620 deferred_in_resp_valid_ = false;
621 deferred_in_resp_len_ = 0u;
622 }
623
624 bool HasDeferredResponseInEpBuffer() const { return deferred_in_resp_valid_; }
625
626 void SetDeferredResponseInEpBuffer(uint16_t len)
627 {
628 deferred_in_resp_len_ = len;
629 deferred_in_resp_valid_ = true;
630 }
631
632 bool SubmitDeferredResponseIfIdle()
633 {
634 if (!deferred_in_resp_valid_ || !ep_data_in_ ||
636 {
637 return false;
638 }
639
640 const uint16_t TX_LEN = deferred_in_resp_len_;
641 if (ep_data_in_->Transfer(TX_LEN) != ErrorCode::OK)
642 {
643 return false;
644 }
645
646 deferred_in_resp_valid_ = false;
647 deferred_in_resp_len_ = 0u;
648 return true;
649 }
650
651 bool IsResponseQueueEmpty() const { return resp_q_count_ == 0u; }
652
653 bool IsResponseQueueFull() const { return resp_q_count_ >= RESP_QUEUE_DEPTH; }
654
655 bool TryBuildAndEnqueueResponse(bool in_isr, const uint8_t* req, uint16_t req_len)
656 {
657 if (!req || IsResponseQueueFull())
658 {
659 return false;
660 }
661
662 auto& slot = resp_q_[resp_q_tail_];
663 uint16_t out_len = 0u;
664 auto ans =
665 ProcessOneCommand(in_isr, req, req_len, slot.payload, RESP_SLOT_SIZE, out_len);
666 UNUSED(ans);
667 slot.len = ClipResponseLength(out_len, RESP_SLOT_SIZE);
668
669 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
670 ++resp_q_count_;
671 return true;
672 }
673
674 uint8_t OutstandingResponseCount() const
675 {
676 const uint8_t IN_FLIGHT =
678 const uint8_t DEFERRED = deferred_in_resp_valid_ ? 1u : 0u;
679 return static_cast<uint8_t>(resp_q_count_ + IN_FLIGHT + DEFERRED);
680 }
681
682 bool EnqueueResponse(const uint8_t* data, uint16_t len)
683 {
684 if (!data || IsResponseQueueFull())
685 {
686 return false;
687 }
688
689 auto& slot = resp_q_[resp_q_tail_];
690 const uint16_t CLIPPED = ClipResponseLength(len, RESP_SLOT_SIZE);
691 slot.len = CLIPPED;
692 if (CLIPPED > 0u)
693 {
694 Memory::FastCopy(slot.payload, data, CLIPPED);
695 }
696
697 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
698 ++resp_q_count_;
699 return true;
700 }
701
702 bool SubmitNextQueuedResponseIfIdle()
703 {
705 IsResponseQueueEmpty())
706 {
707 return false;
708 }
709
710 auto tx_buff = ep_data_in_->GetBuffer();
711 if (!tx_buff.addr_ || tx_buff.size_ == 0u)
712 {
713 return false;
714 }
715
716 auto& slot = resp_q_[resp_q_head_];
717 uint16_t tx_len = slot.len;
718 if (tx_len > tx_buff.size_)
719 {
720 tx_len = static_cast<uint16_t>(tx_buff.size_);
721 }
722
723 if (tx_len > 0u)
724 {
725 Memory::FastCopy(tx_buff.addr_, slot.payload, tx_len);
726 }
727
728 if (ep_data_in_->Transfer(tx_len) != ErrorCode::OK)
729 {
730 return false;
731 }
732
733 resp_q_head_ = NextRespQueueIndex(resp_q_head_);
734 --resp_q_count_;
735 return true;
736 }
737
738 void ArmOutTransferIfIdle()
739 {
740 if (!inited_ || ep_data_out_ == nullptr || ep_data_in_ == nullptr)
741 {
742 return;
743 }
744
746 {
747 return;
748 }
749
750 // 对总未完成响应做背压(in-flight + queued)/ Backpressure on total outstanding
751 // responses (in-flight + queued).
752 if (OutstandingResponseCount() >= MAX_OUTSTANDING_RESPONSES)
753 {
754 return;
755 }
756
757 uint16_t out_rx_len = ep_data_out_->MaxPacketSize();
758 if (out_rx_len == 0u)
759 {
760 out_rx_len = ep_data_out_->MaxTransferSize();
761 }
762 (void)ep_data_out_->Transfer(out_rx_len);
763 }
764
765 private:
766 // ============================================================================
767 // Command dispatch
768 // ============================================================================
769
781 ErrorCode ProcessOneCommand(bool in_isr, const uint8_t* req, uint16_t req_len,
782 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
783 {
784 out_len = 0;
785
786 if (!req || !resp || req_len < 1u || resp_cap < 1u)
787 {
788 if (resp && resp_cap >= 1u)
789 {
790 BuildNotSupportResponse(resp, resp_cap, out_len);
791 }
792 return ErrorCode::ARG_ERR;
793 }
794
795 const uint8_t CMD = req[0];
796
797 switch (CMD)
798 {
799 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::INFO):
800 return HandleInfo(in_isr, req, req_len, resp, resp_cap, out_len);
801 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::HOST_STATUS):
802 return HandleHostStatus(in_isr, req, req_len, resp, resp_cap, out_len);
803 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::CONNECT):
804 return HandleConnect(in_isr, req, req_len, resp, resp_cap, out_len);
805 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::DISCONNECT):
806 return HandleDisconnect(in_isr, req, req_len, resp, resp_cap, out_len);
807 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_CONFIGURE):
808 return HandleTransferConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
809 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER):
810 return HandleTransfer(in_isr, req, req_len, resp, resp_cap, out_len);
811 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_BLOCK):
812 return HandleTransferBlock(in_isr, req, req_len, resp, resp_cap, out_len);
813 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_ABORT):
814 return HandleTransferAbort(in_isr, req, req_len, resp, resp_cap, out_len);
815 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::WRITE_ABORT):
816 return HandleWriteABORT(in_isr, req, req_len, resp, resp_cap, out_len);
817 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::DELAY):
818 return HandleDelay(in_isr, req, req_len, resp, resp_cap, out_len);
819 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::RESET_TARGET):
820 return HandleResetTarget(in_isr, req, req_len, resp, resp_cap, out_len);
821
822 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_PINS):
823 return HandleSWJPins(in_isr, req, req_len, resp, resp_cap, out_len);
824 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_CLOCK):
825 return HandleSWJClock(in_isr, req, req_len, resp, resp_cap, out_len);
826 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_SEQUENCE):
827 return HandleSWJSequence(in_isr, req, req_len, resp, resp_cap, out_len);
828 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_CONFIGURE):
829 return HandleSWDConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
830 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_SEQUENCE):
831 return HandleSWDSequence(in_isr, req, req_len, resp, resp_cap, out_len);
832
833 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS):
834 return HandleQueueCommands(in_isr, req, req_len, resp, resp_cap, out_len);
835 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::EXECUTE_COMMANDS):
836 return HandleExecuteCommands(in_isr, req, req_len, resp, resp_cap, out_len);
837
838 default:
839 (void)BuildUnknowCmdResponse(resp, resp_cap, out_len);
840 return ErrorCode::NOT_SUPPORT;
841 }
842 }
843
851 void BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
852 {
853 if (!resp || resp_cap < 1u)
854 {
855 out_len = 0u;
856 return;
857 }
858 resp[0] = 0xFFu;
859 out_len = 1u;
860 }
861
862 private:
863 // ============================================================================
864 // DAP_Info
865 // ============================================================================
866
867 ErrorCode HandleInfo(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
868 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
869 {
870 if (req_len < 2u)
871 {
872 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::INFO);
873 resp[1] = 0u;
874 out_len = 2u;
875 return ErrorCode::ARG_ERR;
876 }
877
878 const uint8_t INFO_ID = req[1];
879
880 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::INFO);
881
882 switch (INFO_ID)
883 {
884 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::VENDOR):
885 return BuildInfoStringResponse(resp[0], info_.vendor, resp, resp_cap, out_len);
886 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PRODUCT):
887 return BuildInfoStringResponse(resp[0], info_.product, resp, resp_cap, out_len);
888 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::SERIAL_NUMBER):
889 return BuildInfoStringResponse(resp[0], info_.serial, resp, resp_cap, out_len);
890 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::FIRMWARE_VERSION):
891 return BuildInfoStringResponse(resp[0], info_.firmware_ver, resp, resp_cap,
892 out_len);
893
894 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::DEVICE_VENDOR):
895 return BuildInfoStringResponse(resp[0], info_.device_vendor, resp, resp_cap,
896 out_len);
897 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::DEVICE_NAME):
898 return BuildInfoStringResponse(resp[0], info_.device_name, resp, resp_cap,
899 out_len);
900 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::BOARD_VENDOR):
901 return BuildInfoStringResponse(resp[0], info_.board_vendor, resp, resp_cap,
902 out_len);
903 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::BOARD_NAME):
904 return BuildInfoStringResponse(resp[0], info_.board_name, resp, resp_cap,
905 out_len);
906 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PRODUCT_FIRMWARE_VERSION):
907 return BuildInfoStringResponse(resp[0], info_.product_fw_ver, resp, resp_cap,
908 out_len);
909
910 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::CAPABILITIES):
911 return BuildInfoU8Response(resp[0], LibXR::USB::DapLinkV2Def::DAP_CAP_SWD, resp,
912 resp_cap, out_len);
913 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PACKET_COUNT):
914 return BuildInfoU8Response(resp[0], PACKET_COUNT_ADVERTISED, resp, resp_cap,
915 out_len);
916 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PACKET_SIZE):
917 {
918 const uint16_t DAP_PS = GetDapPacketSize();
919 return BuildInfoU16Response(resp[0], DAP_PS, resp, resp_cap, out_len);
920 }
921 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::TIMESTAMP_CLOCK):
922 return BuildInfoU32Response(resp[0], 1000000U, resp, resp_cap, out_len);
923
924 default:
925 resp[1] = 0u;
926 out_len = 2u;
927 return ErrorCode::OK;
928 }
929 }
930
931 ErrorCode BuildInfoStringResponse(uint8_t cmd, const char* str, uint8_t* resp,
932 uint16_t resp_cap, uint16_t& out_len)
933 {
934 resp[0] = cmd;
935 resp[1] = 0u;
936
937 if (!str)
938 {
939 out_len = 2u;
940 return ErrorCode::OK;
941 }
942
943 const size_t N_WITH_NUL = std::strlen(str) + 1; // include '\0'
944 const size_t MAX_PAYLOAD = (resp_cap >= 2u) ? (resp_cap - 2u) : 0u;
945 if (MAX_PAYLOAD == 0u)
946 {
947 out_len = 2u;
948 return ErrorCode::OK;
949 }
950
951 const size_t COPY_N = (N_WITH_NUL > MAX_PAYLOAD) ? MAX_PAYLOAD : N_WITH_NUL;
952 Memory::FastCopy(&resp[2], str, COPY_N);
953
954 // Ensure termination even when truncated
955 resp[2 + COPY_N - 1] = 0x00;
956
957 resp[1] = static_cast<uint8_t>(COPY_N);
958 out_len = static_cast<uint16_t>(2u + COPY_N);
959 return ErrorCode::OK;
960 }
961
962 ErrorCode BuildInfoU8Response(uint8_t cmd, uint8_t val, uint8_t* resp,
963 uint16_t resp_cap, uint16_t& out_len)
964 {
965 if (resp_cap < 3u)
966 {
967 out_len = 0;
968 return ErrorCode::NOT_FOUND;
969 }
970 resp[0] = cmd;
971 resp[1] = 1u;
972 resp[2] = val;
973 out_len = 3u;
974 return ErrorCode::OK;
975 }
976
977 ErrorCode BuildInfoU16Response(uint8_t cmd, uint16_t val, uint8_t* resp,
978 uint16_t resp_cap, uint16_t& out_len)
979 {
980 if (resp_cap < 4u)
981 {
982 out_len = 0;
983 return ErrorCode::NOT_FOUND;
984 }
985 resp[0] = cmd;
986 resp[1] = 2u;
987
988 // Little-endian device only: direct memcpy to payload (alignment-safe).
989 Memory::FastCopy(&resp[2], &val, sizeof(val));
990
991 out_len = 4u;
992 return ErrorCode::OK;
993 }
994
995 ErrorCode BuildInfoU32Response(uint8_t cmd, uint32_t val, uint8_t* resp,
996 uint16_t resp_cap, uint16_t& out_len)
997 {
998 if (resp_cap < 6u)
999 {
1000 out_len = 0;
1001 return ErrorCode::NOT_FOUND;
1002 }
1003 resp[0] = cmd;
1004 resp[1] = 4u;
1005
1006 // Little-endian device only: direct memcpy to payload (alignment-safe).
1007 Memory::FastCopy(&resp[2], &val, sizeof(val));
1008
1009 out_len = 6u;
1010 return ErrorCode::OK;
1011 }
1012
1013 private:
1014 // ============================================================================
1015 // Simple control handlers
1016 // ============================================================================
1017
1018 ErrorCode HandleHostStatus(bool /*in_isr*/, const uint8_t* /*req*/,
1019 uint16_t /*req_len*/, uint8_t* resp, uint16_t resp_cap,
1020 uint16_t& out_len)
1021 {
1022 if (resp_cap < 2u)
1023 {
1024 out_len = 0;
1025 return ErrorCode::NOT_FOUND;
1026 }
1027 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::HOST_STATUS);
1028 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1029 out_len = 2u;
1030 return ErrorCode::OK;
1031 }
1032
1033 ErrorCode HandleConnect(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1034 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1035 {
1036 if (resp_cap < 2u)
1037 {
1038 out_len = 0;
1039 return ErrorCode::NOT_FOUND;
1040 }
1041
1042 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::CONNECT);
1043
1044 uint8_t port = 0u;
1045 if (req_len >= 2u)
1046 {
1047 port = req[1];
1048 }
1049
1050 // SWD-only
1051 if (port == 0u || port == ToU8(LibXR::USB::DapLinkV2Def::Port::SWD))
1052 {
1053 (void)swd_.EnterSwd();
1054 (void)swd_.SetClockHz(swj_clock_hz_);
1055
1056 dap_state_.debug_port = LibXR::USB::DapLinkV2Def::DebugPort::SWD;
1057 dap_state_.transfer_abort = false;
1058
1059 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Port::SWD);
1060 }
1061 else
1062 {
1063 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Port::DISABLED);
1064 }
1065
1066 out_len = 2u;
1067 return ErrorCode::OK;
1068 }
1069
1070 ErrorCode HandleDisconnect(bool /*in_isr*/, const uint8_t* /*req*/,
1071 uint16_t /*req_len*/, uint8_t* resp, uint16_t resp_cap,
1072 uint16_t& out_len)
1073 {
1074 if (resp_cap < 2u)
1075 {
1076 out_len = 0;
1077 return ErrorCode::NOT_FOUND;
1078 }
1079
1080 swd_.Close();
1081 dap_state_.debug_port = LibXR::USB::DapLinkV2Def::DebugPort::DISABLED;
1082 dap_state_.transfer_abort = false;
1083
1084 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::DISCONNECT);
1085 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1086 out_len = 2u;
1087 return ErrorCode::OK;
1088 }
1089
1090 ErrorCode HandleTransferConfigure(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1091 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1092 {
1093 if (resp_cap < 2u)
1094 {
1095 out_len = 0;
1096 return ErrorCode::NOT_FOUND;
1097 }
1098
1099 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_CONFIGURE);
1100
1101 // Req: [0]=0x04 [1]=idle_cycles [2..3]=wait_retry [4..5]=match_retry
1102 if (req_len < 6u)
1103 {
1104 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1105 out_len = 2u;
1106 return ErrorCode::ARG_ERR;
1107 }
1108
1109 const uint8_t IDLE = req[1];
1110
1111 uint16_t wait_retry = 0u;
1112 uint16_t match_retry = 0u;
1113 Memory::FastCopy(&wait_retry, &req[2], sizeof(wait_retry));
1114 Memory::FastCopy(&match_retry, &req[4], sizeof(match_retry));
1115
1117 dap_state_.transfer_cfg.retry_count = wait_retry;
1118 dap_state_.transfer_cfg.match_retry = match_retry;
1119
1120 // Map to SWD transaction policy
1121 Debug::Swd::TransferPolicy pol = swd_.GetTransferPolicy();
1122 pol.idle_cycles = IDLE;
1123 pol.wait_retry = wait_retry;
1124 swd_.SetTransferPolicy(pol);
1125
1126 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1127 out_len = 2u;
1128 return ErrorCode::OK;
1129 }
1130
1131 ErrorCode HandleTransferAbort(bool /*in_isr*/, const uint8_t* /*req*/,
1132 uint16_t /*req_len*/, uint8_t* resp, uint16_t resp_cap,
1133 uint16_t& out_len)
1134 {
1135 if (resp_cap < 2u)
1136 {
1137 out_len = 0;
1138 return ErrorCode::NOT_FOUND;
1139 }
1140
1141 SetTransferAbortFlag(true);
1142
1143 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_ABORT);
1144 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1145 out_len = 2u;
1146 return ErrorCode::OK;
1147 }
1148
1149 ErrorCode HandleWriteABORT(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1150 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1151 {
1152 if (resp_cap < 2u)
1153 {
1154 out_len = 0;
1155 return ErrorCode::NOT_FOUND;
1156 }
1157
1158 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::WRITE_ABORT);
1159
1160 if (req_len < 6u)
1161 {
1162 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1163 out_len = 2u;
1164 return ErrorCode::ARG_ERR;
1165 }
1166
1167 uint32_t flags = 0u;
1168 Memory::FastCopy(&flags, &req[2], sizeof(flags));
1169
1170 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1171
1172 const ErrorCode EC = swd_.WriteAbortTxn(flags, ack);
1173 resp[1] = (EC == ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1174 ? ToU8(LibXR::USB::DapLinkV2Def::Status::OK)
1175 : ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1176
1177 out_len = 2u;
1178 return ErrorCode::OK;
1179 }
1180
1181 ErrorCode HandleDelay(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1182 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1183 {
1184 if (resp_cap < 2u)
1185 {
1186 out_len = 0;
1187 return ErrorCode::NOT_FOUND;
1188 }
1189
1190 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::DELAY);
1191
1192 if (req_len < 3u)
1193 {
1194 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1195 out_len = 2u;
1196 return ErrorCode::ARG_ERR;
1197 }
1198
1199 uint16_t us = 0u;
1200 Memory::FastCopy(&us, &req[1], sizeof(us));
1201
1203
1204 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1205 out_len = 2u;
1206 return ErrorCode::OK;
1207 }
1208
1209 ErrorCode HandleResetTarget(bool in_isr, const uint8_t* /*req*/, uint16_t /*req_len*/,
1210 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1211 {
1212 if (!resp || resp_cap < 3u)
1213 {
1214 out_len = 0u;
1215 return ErrorCode::NOT_FOUND;
1216 }
1217
1218 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::RESET_TARGET);
1219
1220 uint8_t execute = 0u;
1221
1222 if (nreset_gpio_ != nullptr)
1223 {
1224 DriveReset(false);
1225 DelayUsIfAllowed(in_isr, 1000u);
1226 DriveReset(true);
1227 DelayUsIfAllowed(in_isr, 1000u);
1228 execute = 1u;
1229 }
1230
1231 // 关键:无论是否实现 reset,都返回 DAP_OK;未实现则 Execute=0
1232 // Key: Always return DAP_OK; if not implemented, Execute=0.
1233 resp[1] = DAP_OK;
1234 resp[2] = execute;
1235 out_len = 3u;
1236 return ErrorCode::OK;
1237 }
1238
1239 private:
1240 // ============================================================================
1241 // SWJ / SWD handlers
1242 // ============================================================================
1243 ErrorCode HandleSWJPins(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1244 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1245 {
1246 if (!resp || resp_cap < 2u)
1247 {
1248 out_len = 0u;
1249 return ErrorCode::NOT_FOUND;
1250 }
1251
1252 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_PINS);
1253
1254 // Req: [0]=0x10 [1]=PinOut [2]=PinSelect [3..6]=PinWait(us)
1255 if (!req || req_len < 7u)
1256 {
1257 resp[1] = 0u;
1258 out_len = 2u;
1259 return ErrorCode::ARG_ERR;
1260 }
1261
1262 const uint8_t PIN_OUT = req[1];
1263 const uint8_t PIN_SEL = req[2];
1264
1265 uint32_t wait_us = 0u;
1266 Memory::FastCopy(&wait_us, &req[3], sizeof(wait_us));
1267
1268 // 0) Latch requested states into shadow for ALL selected pins (even if unsupported)
1269 swj_shadow_ = static_cast<uint8_t>((swj_shadow_ & static_cast<uint8_t>(~PIN_SEL)) |
1270 (PIN_OUT & PIN_SEL));
1271
1272 // 1) Only physically support nRESET (best-effort)
1273 if ((PIN_SEL & LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET) != 0u)
1274 {
1275 const bool LEVEL_HIGH =
1276 ((PIN_OUT & LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET) != 0u);
1277 // DriveReset updates last_nreset_level_high_ and shadow, and writes GPIO if
1278 // present.
1279 DriveReset(LEVEL_HIGH);
1280 }
1281
1282 // Read helper: start from shadow; override nRESET with physical level if wired.
1283 auto read_pins = [&]() -> uint8_t
1284 {
1285 uint8_t pin_in = swj_shadow_;
1286
1287 if (nreset_gpio_ != nullptr)
1288 {
1289 if (nreset_gpio_->Read())
1290 {
1291 pin_in |= LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET;
1292 }
1293 else
1294 {
1295 pin_in = static_cast<uint8_t>(
1296 pin_in & static_cast<uint8_t>(~LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET));
1297 }
1298 }
1299
1300 return pin_in;
1301 };
1302
1303 // 2) PinWait: wait until (PinInput & PinSelect) matches (PinOut & PinSelect), or
1304 // timeout. Since SWCLK/SWDIO are shadow-only now, their selected bits will already
1305 // match immediately.
1306 uint8_t pin_in = 0u;
1307
1308 if (wait_us == 0u || PIN_SEL == 0u)
1309 {
1310 pin_in = read_pins();
1311 }
1312 else
1313 {
1314 const uint64_t START = LibXR::Timebase::GetMicroseconds();
1315 const uint8_t EXPECT = static_cast<uint8_t>(PIN_OUT & PIN_SEL);
1316
1317 do
1318 {
1319 pin_in = read_pins();
1320 if ((pin_in & PIN_SEL) == EXPECT)
1321 {
1322 break;
1323 }
1324 } while ((static_cast<uint64_t>(LibXR::Timebase::GetMicroseconds()) - START) <
1325 wait_us);
1326 }
1327
1328 resp[1] = pin_in;
1329 out_len = 2u;
1330 return ErrorCode::OK;
1331 }
1332
1333 ErrorCode HandleSWJClock(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1334 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1335 {
1336 if (resp_cap < 2u)
1337 {
1338 out_len = 0;
1339 return ErrorCode::NOT_FOUND;
1340 }
1341
1342 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_CLOCK);
1343
1344 if (req_len < 5u)
1345 {
1346 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1347 out_len = 2u;
1348 return ErrorCode::ARG_ERR;
1349 }
1350
1351 uint32_t hz = 0u;
1352 Memory::FastCopy(&hz, &req[1], sizeof(hz));
1353
1354 swj_clock_hz_ = hz;
1355 (void)swd_.SetClockHz(hz);
1356
1357 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1358 out_len = 2u;
1359 return ErrorCode::OK;
1360 }
1361
1362 ErrorCode HandleSWJSequence(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1363 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1364 {
1365 if (!resp || resp_cap < 2u)
1366 {
1367 out_len = 0u;
1368 return ErrorCode::NOT_FOUND;
1369 }
1370
1371 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_SEQUENCE);
1372 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1373 out_len = 2u;
1374
1375 // Req: [0]=0x12 [1]=bit_count(0=>256) [2..]=data (LSB-first)
1376 if (!req || req_len < 2u)
1377 {
1378 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1379 return ErrorCode::ARG_ERR;
1380 }
1381
1382 const uint8_t RAW_COUNT = req[1];
1383 const uint32_t BIT_COUNT =
1384 (RAW_COUNT == 0u) ? 256u : static_cast<uint32_t>(RAW_COUNT);
1385 const uint32_t BYTE_COUNT = (BIT_COUNT + 7u) / 8u;
1386
1387 if (2u + BYTE_COUNT > req_len)
1388 {
1389 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1390 return ErrorCode::ARG_ERR;
1391 }
1392
1393 const uint8_t* data = &req[2];
1394
1395 // Delegate to SwdPort implementation (no RawMode / no pin-level control here)
1396 const ErrorCode EC = swd_.SeqWriteBits(BIT_COUNT, data);
1397 if (EC != ErrorCode::OK)
1398 {
1399 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1400 // Keep transport-level OK so host still gets a valid response.
1401 return ErrorCode::OK;
1402 }
1403
1404 // Maintain shadow semantics: keep SWCLK=0, SWDIO=last bit
1405 swj_shadow_ = static_cast<uint8_t>(
1406 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV2Def::DAP_SWJ_SWCLK_TCK));
1407
1408 bool last_swdio = false;
1409 if (BIT_COUNT != 0u)
1410 {
1411 const uint32_t LAST_I = BIT_COUNT - 1u;
1412 last_swdio = (((data[LAST_I / 8u] >> (LAST_I & 7u)) & 0x01u) != 0u);
1413 }
1414
1415 if (last_swdio)
1416 {
1417 swj_shadow_ |= LibXR::USB::DapLinkV2Def::DAP_SWJ_SWDIO_TMS;
1418 }
1419 else
1420 {
1421 swj_shadow_ = static_cast<uint8_t>(
1422 swj_shadow_ &
1423 static_cast<uint8_t>(~LibXR::USB::DapLinkV2Def::DAP_SWJ_SWDIO_TMS));
1424 }
1425
1426 return ErrorCode::OK;
1427 }
1428
1429 ErrorCode HandleSWDConfigure(bool /*in_isr*/, const uint8_t* /*req*/,
1430 uint16_t /*req_len*/, uint8_t* resp, uint16_t resp_cap,
1431 uint16_t& out_len)
1432 {
1433 if (resp_cap < 2u)
1434 {
1435 out_len = 0;
1436 return ErrorCode::NOT_FOUND;
1437 }
1438
1439 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_CONFIGURE);
1440
1441 // Best-effort parse (optional). Keep compatibility by returning OK.
1442 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1443 out_len = 2u;
1444 return ErrorCode::OK;
1445 }
1446
1447 ErrorCode HandleSWDSequence(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1448 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1449 {
1450 if (!req || !resp || resp_cap < 2u)
1451 {
1452 out_len = 0u;
1453 return ErrorCode::ARG_ERR;
1454 }
1455
1456 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_SEQUENCE);
1457 resp[1] = DAP_OK;
1458 out_len = 2u;
1459
1460 // Req: [0]=0x1D [1]=SequenceCount [ ... sequences ... ]
1461 // Each sequence:
1462 // INFO: [7]=Direction (1=input,0=output), [5:0]=cycles (0=>64)
1463 // If output: followed by ceil(cycles/8) bytes data (LSB-first)
1464 // If input : no data in request; response appends ceil(cycles/8) bytes data
1465 // (LSB-first)
1466 if (req_len < 2u)
1467 {
1468 resp[1] = DAP_ERROR;
1469 out_len = 2u;
1470 return ErrorCode::ARG_ERR;
1471 }
1472
1473 const uint8_t SEQ_CNT = req[1];
1474 uint16_t req_off = 2u;
1475 uint16_t resp_off = 2u;
1476
1477 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1478 {
1479 if (req_off >= req_len)
1480 {
1481 resp[1] = DAP_ERROR;
1482 out_len = 2u;
1483 return ErrorCode::ARG_ERR;
1484 }
1485
1486 const uint8_t INFO = req[req_off++];
1487
1488 uint32_t cycles = static_cast<uint32_t>(INFO & 0x3Fu);
1489 if (cycles == 0u)
1490 {
1491 cycles = 64u;
1492 }
1493
1494 const bool MODE_IN = ((INFO & 0x80u) != 0u);
1495 const uint16_t BYTES = static_cast<uint16_t>((cycles + 7u) / 8u);
1496
1497 if (!MODE_IN)
1498 {
1499 // Output: data bytes are in request
1500 if (req_off + BYTES > req_len)
1501 {
1502 resp[1] = DAP_ERROR;
1503 out_len = 2u;
1504 return ErrorCode::ARG_ERR;
1505 }
1506
1507 const uint8_t* data = &req[req_off];
1508 req_off = static_cast<uint16_t>(req_off + BYTES);
1509
1510 const ErrorCode EC = swd_.SeqWriteBits(cycles, data);
1511 if (EC != ErrorCode::OK)
1512 {
1513 resp[1] = DAP_ERROR;
1514 out_len = 2u;
1515 // Return OK so host gets a valid response packet
1516 return ErrorCode::OK;
1517 }
1518 }
1519 else
1520 {
1521 // Input: captured data is appended to response
1522 if (resp_off + BYTES > resp_cap)
1523 {
1524 resp[1] = DAP_ERROR;
1525 out_len = 2u;
1526 return ErrorCode::NOT_FOUND;
1527 }
1528
1529 Memory::FastSet(&resp[resp_off], 0, BYTES);
1530
1531 const ErrorCode EC = swd_.SeqReadBits(cycles, &resp[resp_off]);
1532 if (EC != ErrorCode::OK)
1533 {
1534 resp[1] = DAP_ERROR;
1535 out_len = 2u;
1536 return ErrorCode::OK;
1537 }
1538
1539 resp_off = static_cast<uint16_t>(resp_off + BYTES);
1540 }
1541 }
1542
1543 out_len = resp_off;
1544 return ErrorCode::OK;
1545 }
1546
1547 ErrorCode HandleQueueCommands(bool /*in_isr*/, const uint8_t* /*req*/,
1548 uint16_t /*req_len*/, uint8_t* resp, uint16_t resp_cap,
1549 uint16_t& out_len)
1550 {
1551 return BuildCmdStatusResponse(
1552 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS), DAP_ERROR, resp,
1553 resp_cap, out_len);
1554 }
1555
1556 ErrorCode HandleExecuteCommands(bool /*in_isr*/, const uint8_t* /*req*/,
1557 uint16_t /*req_len*/, uint8_t* resp, uint16_t resp_cap,
1558 uint16_t& out_len)
1559 {
1560 return BuildCmdStatusResponse(
1561 ToU8(LibXR::USB::DapLinkV2Def::CommandId::EXECUTE_COMMANDS), DAP_ERROR, resp,
1562 resp_cap, out_len);
1563 }
1564
1565 private:
1566 // ============================================================================
1567 // Transfer helpers
1568 // ============================================================================
1569
1570 uint8_t MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack) const
1571 {
1572 static constexpr uint8_t ACK_MAP[8] = {7u, 1u, 2u, 7u, 4u, 7u, 7u, 7u};
1573 return ACK_MAP[static_cast<uint8_t>(ack) & 0x07u];
1574 }
1575
1576 void SetTransferAbortFlag(bool on) { dap_state_.transfer_abort = on; }
1577
1578 private:
1579 // ============================================================================
1580 // DAP_Transfer / DAP_TransferBlock
1581 // ============================================================================
1582
1583 // 说明:以下长函数保持原样;本 cpp 文件不补充函数级注释,hpp 中再统一给出接口说明。
1584 // Note: The following long functions are kept as-is; no function-level docs in this
1585 // cpp. HPP will carry API docs.
1586
1587 ErrorCode HandleTransfer(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
1588 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1589 {
1590 out_len = 0u;
1591 if (!req || !resp || resp_cap < 3u)
1592 {
1593 return ErrorCode::ARG_ERR;
1594 }
1595
1596 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER);
1597 resp[1] = 0u; // response_count = #successful transfers
1598 resp[2] = 0u; // response_value (ACK bits / ERROR / MISMATCH)
1599 uint16_t resp_off = 3u;
1600
1601 // Req: [0]=CMD [1]=DAP index [2]=count [3..]=transfers...
1602 if (req_len < 3u)
1603 {
1604 resp[2] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1605 out_len = 3u;
1606 return ErrorCode::ARG_ERR;
1607 }
1608
1610 {
1611 dap_state_.transfer_abort = false;
1612 resp[2] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1613 out_len = 3u;
1614 return ErrorCode::OK;
1615 }
1616
1617 const uint8_t COUNT = req[2];
1618 uint16_t req_off = 3u;
1619
1620 auto push_u32 = [&](uint32_t v) -> bool
1621 {
1622 if (resp_off + 4u > resp_cap)
1623 {
1624 return false;
1625 }
1626 Memory::FastCopy(&resp[resp_off], &v, sizeof(v));
1627 resp_off = static_cast<uint16_t>(resp_off + 4u);
1628 return true;
1629 };
1630
1631 auto push_timestamp = [&]() -> bool
1632 {
1633 const uint32_t T = static_cast<uint32_t>(LibXR::Timebase::GetMicroseconds());
1634 return push_u32(T);
1635 };
1636
1637 auto ensure_space = [&](uint16_t bytes) -> bool
1638 { return (resp_off + bytes) <= resp_cap; };
1639
1640 auto bytes_for_read = [&](bool need_ts) -> uint16_t
1641 { return static_cast<uint16_t>(need_ts ? 8u : 4u); };
1642
1643 uint8_t response_count = 0u;
1644 uint8_t response_value = 0u; // 与参考实现一致:未发生 transfer 时为 0
1645
1646 bool check_write = false; // 是否需要末尾 RDBUFF check(用于 write fault 冲刷)
1647
1648 // -------- posted-read pipeline state (AP read only) --------
1649 struct PendingApRead
1650 {
1651 bool valid = false;
1652 bool need_ts = false; // 该 AP read transfer 是否要求 timestamp
1653 } pending;
1654
1655 auto emit_read_with_ts = [&](bool need_ts, uint32_t data) -> bool
1656 {
1657 if (need_ts)
1658 {
1659 if (!push_timestamp())
1660 {
1661 return false;
1662 }
1663 }
1664 if (!push_u32(data))
1665 {
1666 return false;
1667 }
1668 response_count++;
1669 return true;
1670 };
1671
1672 // 通过读 DP_RDBUFF 完成 pending AP read(用于:序列结束/被非 AP-read 打断/异常收尾)
1673 auto complete_pending_by_rdbuff = [&]() -> bool
1674 {
1675 if (!pending.valid)
1676 {
1677 return true;
1678 }
1679
1680 if (!ensure_space(bytes_for_read(pending.need_ts)))
1681 {
1682 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1683 return false;
1684 }
1685
1686 uint32_t rdata = 0u;
1687 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1688 const ErrorCode EC = swd_.DpReadRdbuffTxn(rdata, ack);
1689
1690 const uint8_t V = MapAckToDapResp(ack);
1691 if (V != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
1692 {
1693 response_value = V;
1694 return false;
1695 }
1696 if (EC != ErrorCode::OK)
1697 {
1698 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1699 return false;
1700 }
1701
1702 if (!emit_read_with_ts(pending.need_ts, rdata))
1703 {
1704 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1705 return false;
1706 }
1707
1708 pending.valid = false;
1709 pending.need_ts = false;
1710
1711 // 读过 RDBUFF,等价于做过一次“posted/fault flush”
1712 check_write = false;
1713
1714 // 成功路径保持 OK
1715 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
1716 return true;
1717 };
1718
1719 // 在处理“非 AP normal read”之前,必须先把 pending flush 掉(保证响应顺序与 pipeline
1720 // 不紊乱)
1721 auto flush_pending_if_any = [&]() -> bool
1722 { return pending.valid ? complete_pending_by_rdbuff() : true; };
1723
1724 // -------- main loop --------
1725 for (uint32_t i = 0; i < COUNT; ++i)
1726 {
1727 if (req_off >= req_len)
1728 {
1729 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1730 break;
1731 }
1732
1733 const uint8_t RQ = req[req_off++];
1734
1735 const bool AP = LibXR::USB::DapLinkV2Def::req_is_ap(RQ);
1736 const bool RNW = LibXR::USB::DapLinkV2Def::req_is_read(RQ);
1737 const uint8_t ADDR2B = LibXR::USB::DapLinkV2Def::req_addr2b(RQ);
1738
1740 const bool MATCH_VALUE =
1741 ((RQ & LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
1742 const bool MATCH_MASK =
1743 ((RQ & LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_MASK) != 0u);
1744
1745 // 规范:timestamp 不能与 match 位组合
1746 if (TS && (MATCH_VALUE || MATCH_MASK))
1747 {
1748 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1749 break;
1750 }
1751
1752 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1753 ErrorCode ec = ErrorCode::OK;
1754
1755 if (!RNW)
1756 {
1757 // ---------------- WRITE ----------------
1758 // 写/配置类操作不参与 AP posted pipeline;先 flush pending
1759 if (!flush_pending_if_any())
1760 {
1761 break;
1762 }
1763
1764 if (req_off + 4u > req_len)
1765 {
1766 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1767 break;
1768 }
1769
1770 uint32_t wdata = 0u;
1771 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
1772 req_off = static_cast<uint16_t>(req_off + 4u);
1773
1774 if (MATCH_MASK)
1775 {
1776 match_mask_ = wdata;
1777 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
1778 response_count++; // MATCH_MASK 视为成功 transfer
1779 continue;
1780 }
1781
1782 if (AP)
1783 {
1784 ec = swd_.ApWriteTxn(ADDR2B, wdata, ack);
1785 }
1786 else
1787 {
1788 ec = swd_.DpWriteTxn(static_cast<LibXR::Debug::SwdProtocol::DpWriteReg>(ADDR2B),
1789 wdata, ack);
1790 }
1791
1792 response_value = MapAckToDapResp(ack);
1793 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
1794 {
1795 break;
1796 }
1797 if (ec != ErrorCode::OK)
1798 {
1799 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1800 break;
1801 }
1802
1803 if (TS)
1804 {
1805 if (!push_timestamp())
1806 {
1807 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1808 break;
1809 }
1810 }
1811
1812 response_count++;
1813 check_write = true;
1814 }
1815 else
1816 {
1817 // ---------------- READ ----------------
1818
1819 if (MATCH_VALUE)
1820 {
1821 // MATCH_VALUE 不回传 data;为简化语义,先 flush pending,再走原逻辑(AP read
1822 // 仍用 ApReadTxn)
1823 if (!flush_pending_if_any())
1824 {
1825 break;
1826 }
1827
1828 if (req_off + 4u > req_len)
1829 {
1830 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1831 break;
1832 }
1833
1834 uint32_t match_val = 0u;
1835 Memory::FastCopy(&match_val, &req[req_off], sizeof(match_val));
1836 req_off = static_cast<uint16_t>(req_off + 4u);
1837
1838 uint32_t rdata = 0u;
1839 uint32_t retry = dap_state_.transfer_cfg.match_retry;
1840 bool matched = false;
1841
1842 while (true)
1843 {
1844 if (AP)
1845 {
1846 ec = swd_.ApReadTxn(ADDR2B, rdata, ack); // 内含 RDBUFF
1847 if (ec == ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1848 {
1849 // ApReadTxn 读过 RDBUFF,等价 flush
1850 check_write = false;
1851 }
1852 }
1853 else
1854 {
1855 ec = swd_.DpReadTxn(
1856 static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B), rdata, ack);
1857 }
1858
1859 response_value = MapAckToDapResp(ack);
1860 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
1861 {
1862 break;
1863 }
1864 if (ec != ErrorCode::OK)
1865 {
1866 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1867 break;
1868 }
1869
1870 if ((rdata & match_mask_) == (match_val & match_mask_))
1871 {
1872 matched = true;
1873 break;
1874 }
1875
1876 if (retry == 0u)
1877 {
1878 break;
1879 }
1880 --retry;
1881 }
1882
1883 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
1884 {
1885 break;
1886 }
1887
1888 if (!matched)
1889 {
1890 response_value =
1891 static_cast<uint8_t>(LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK |
1892 LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MISMATCH);
1893 // MISMATCH 不计入 response_count
1894 break;
1895 }
1896
1897 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
1898 response_count++;
1899 continue;
1900 }
1901
1902 // ---- Normal read ----
1903 if (!AP)
1904 {
1905 // DP read:不参与 pipeline;先 flush pending
1906 if (!flush_pending_if_any())
1907 {
1908 break;
1909 }
1910
1911 uint32_t rdata = 0u;
1912 ec = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
1913 rdata, ack);
1914
1915 response_value = MapAckToDapResp(ack);
1916 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
1917 {
1918 break;
1919 }
1920 if (ec != ErrorCode::OK)
1921 {
1922 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1923 break;
1924 }
1925
1926 if (!ensure_space(bytes_for_read(TS)))
1927 {
1928 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1929 break;
1930 }
1931
1932 if (!emit_read_with_ts(TS, rdata))
1933 {
1934 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1935 break;
1936 }
1937
1938 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
1939 continue;
1940 }
1941
1942 // AP normal read:posted-read pipeline
1943 if (!pending.valid)
1944 {
1945 // 这是该段连续 AP reads 的第一笔:发起一次 AP read(posted),丢弃其 returned
1946 // posted data
1947 uint32_t dummy_posted = 0u;
1948 ec = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
1949
1950 response_value = MapAckToDapResp(ack);
1951 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
1952 {
1953 break;
1954 }
1955 if (ec != ErrorCode::OK)
1956 {
1957 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1958 {
1959 break;
1960 }
1961 }
1962
1963 pending.valid = true;
1964 pending.need_ts = TS;
1965
1966 // 该 transfer 尚未“完成”(数据要等下一次 AP read 或末尾 RDBUFF)
1967 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
1968 }
1969 else
1970 {
1971 // pending 存在:本次 AP read 的 returned posted data = 上一笔 AP read 的结果
1972 if (!ensure_space(bytes_for_read(pending.need_ts)))
1973 {
1974 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1975 break;
1976 }
1977
1978 uint32_t posted_prev = 0u;
1979 ec = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
1980
1981 const uint8_t CUR_V = MapAckToDapResp(ack);
1982 if (CUR_V != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK || ec != ErrorCode::OK)
1983 {
1984 // 本次 AP read 没跑通:尽量用 RDBUFF 把 pending 补齐(否则 count 会少一笔且
1985 // pipeline 残留)
1986 const uint8_t PROOR_FAIL =
1987 (CUR_V != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
1988 ? CUR_V
1989 : LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
1990
1991 if (!complete_pending_by_rdbuff())
1992 {
1993 // pending 本身失败:按“更早失败”返回(complete_pending_by_rdbuff 已写
1994 // response_value)
1995 break;
1996 }
1997
1998 // pending 补齐成功:保留“当前失败”
1999 response_value = PROOR_FAIL;
2000 break;
2001 }
2002
2003 // 本次 AP read 成功:先回传 pending(用 posted_prev),再把“本次”设为新的
2004 // pending
2005 if (!emit_read_with_ts(pending.need_ts, posted_prev))
2006 {
2007 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2008 break;
2009 }
2010
2011 pending.valid = true;
2012 pending.need_ts = TS;
2013
2014 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2015 }
2016 }
2017
2019 {
2020 dap_state_.transfer_abort = false;
2021 break;
2022 }
2023 }
2024
2025 // 若仍有 pending AP read:
2026 // - 若当前 response_value=OK:正常收尾(读一次 RDBUFF)
2027 // - 若当前 response_value!=OK:尝试先补齐 pending;补齐成功则保留原失败,否则以
2028 // pending 失败为准
2029 if (pending.valid)
2030 {
2031 const uint8_t PRIOR_FAIL = response_value;
2032
2033 if (!complete_pending_by_rdbuff())
2034 {
2035 // 以 pending 的失败为准(已写 response_value)
2036 }
2037 else
2038 {
2039 // pending 补齐成功:保留原失败(如果原本就是 OK 则维持 OK)
2040 if (PRIOR_FAIL != 0u && PRIOR_FAIL != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2041 {
2042 response_value = PRIOR_FAIL;
2043 }
2044 }
2045 }
2046
2047 // 末尾写入冲刷:若全部 OK 且发生过真实 write,且期间未通过 RDBUFF flush,则做一次
2048 // DP_RDBUFF read (discard)
2049 if (response_value == LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK && check_write)
2050 {
2051 uint32_t dummy = 0u;
2052 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2053 const ErrorCode EC = swd_.DpReadRdbuffTxn(dummy, ack);
2054 const uint8_t V = MapAckToDapResp(ack);
2055
2056 if (V != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2057 {
2058 response_value = V;
2059 }
2060 else if (EC != ErrorCode::OK)
2061 {
2062 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2063 }
2064 }
2065
2066 resp[1] = response_count;
2067 resp[2] = response_value;
2068 out_len = resp_off;
2069 return ErrorCode::OK;
2070 }
2071
2072 ErrorCode HandleTransferBlock(bool /*in_isr*/, const uint8_t* req, uint16_t req_len,
2073 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
2074 {
2075 // Req: [0]=0x06 [1]=index [2..3]=count [4]=request [5..]=data(write)
2076 // Resp: [0]=0x06 [1..2]=done [3]=resp [4..]=data(read)
2077 if (!resp || resp_cap < 4u)
2078 {
2079 out_len = 0u;
2080 return ErrorCode::NOT_FOUND;
2081 }
2082
2083 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_BLOCK);
2084 resp[1] = 0u;
2085 resp[2] = 0u;
2086 resp[3] = 0u;
2087 out_len = 4u;
2088
2089 if (!req || req_len < 5u)
2090 {
2091 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2092 return ErrorCode::ARG_ERR;
2093 }
2094
2096 {
2097 dap_state_.transfer_abort = false;
2098 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2099 return ErrorCode::OK;
2100 }
2101
2102 uint16_t count = 0u;
2103 Memory::FastCopy(&count, &req[2], sizeof(count));
2104
2105 const uint8_t DAP_RQ = req[4];
2106
2107 // TransferBlock does not support match or timestamp
2108 if ((DAP_RQ & (LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_VALUE |
2109 LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
2110 {
2111 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2112 return ErrorCode::NOT_SUPPORT;
2113 }
2115 {
2116 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2117 return ErrorCode::NOT_SUPPORT;
2118 }
2119
2120 // Count==0: return OK
2121 if (count == 0u)
2122 {
2123 const uint16_t DONE0 = 0u;
2124 Memory::FastCopy(&resp[1], &DONE0, sizeof(DONE0));
2125 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2126 out_len = 4u;
2127 return ErrorCode::OK;
2128 }
2129
2130 const bool AP = LibXR::USB::DapLinkV2Def::req_is_ap(DAP_RQ);
2131 const bool RNW = LibXR::USB::DapLinkV2Def::req_is_read(DAP_RQ);
2132 const uint8_t ADDR2B = LibXR::USB::DapLinkV2Def::req_addr2b(DAP_RQ);
2133
2134 uint16_t done = 0u;
2135 uint8_t xresp = 0u;
2136
2137 uint16_t req_off = 5u;
2138 uint16_t resp_off = 4u;
2139
2140 // WRITE path: keep original behavior
2141 if (!RNW)
2142 {
2143 const uint32_t REQ_NEED =
2144 static_cast<uint32_t>(req_off) + (static_cast<uint32_t>(count) * 4u);
2145 if (REQ_NEED > req_len)
2146 {
2147 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2148 Memory::FastCopy(&resp[1], &done, sizeof(done));
2149 resp[3] = xresp;
2150 out_len = resp_off;
2151 return ErrorCode::OK;
2152 }
2153
2154 for (uint32_t i = 0; i < count; ++i)
2155 {
2156 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2157 ErrorCode ec = ErrorCode::OK;
2158
2159 uint32_t wdata = 0u;
2160 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
2161 req_off = static_cast<uint16_t>(req_off + 4u);
2162
2163 if (AP)
2164 {
2165 ec = swd_.ApWriteTxn(ADDR2B, wdata, ack);
2166 }
2167 else
2168 {
2169 ec = swd_.DpWriteTxn(static_cast<LibXR::Debug::SwdProtocol::DpWriteReg>(ADDR2B),
2170 wdata, ack);
2171 }
2172
2173 xresp = MapAckToDapResp(ack);
2174 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2175 {
2176 break;
2177 }
2178 if (ec != ErrorCode::OK)
2179 {
2180 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2181 break;
2182 }
2183
2184 done = static_cast<uint16_t>(i + 1u);
2185 }
2186
2187 Memory::FastCopy(&resp[1], &done, sizeof(done));
2188 resp[3] = xresp;
2189 out_len = resp_off;
2190 return ErrorCode::OK;
2191 }
2192
2193 // READ path
2194 if (!AP)
2195 {
2196 const uint32_t RESP_NEED =
2197 static_cast<uint32_t>(resp_off) + (static_cast<uint32_t>(count) * 4u);
2198 if (RESP_NEED > resp_cap)
2199 {
2200 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2201 Memory::FastCopy(&resp[1], &done, sizeof(done));
2202 resp[3] = xresp;
2203 out_len = resp_off;
2204 return ErrorCode::OK;
2205 }
2206
2207 // DP read: keep original behavior
2208 for (uint32_t i = 0; i < count; ++i)
2209 {
2210 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2211 ErrorCode ec = ErrorCode::OK;
2212 uint32_t rdata = 0u;
2213
2214 ec = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
2215 rdata, ack);
2216
2217 xresp = MapAckToDapResp(ack);
2218 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2219 {
2220 break;
2221 }
2222
2223 if (ec != ErrorCode::OK)
2224 {
2225 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2226 break;
2227 }
2228
2229 Memory::FastCopy(&resp[resp_off], &rdata, sizeof(rdata));
2230 resp_off = static_cast<uint16_t>(resp_off + 4u);
2231 done = static_cast<uint16_t>(i + 1u);
2232 }
2233
2234 Memory::FastCopy(&resp[1], &done, sizeof(done));
2235 resp[3] = xresp;
2236 out_len = resp_off;
2237 return ErrorCode::OK;
2238 }
2239
2240 // AP read: posted-read pipeline
2241 {
2242 const uint32_t RESP_NEED =
2243 static_cast<uint32_t>(resp_off) + (static_cast<uint32_t>(count) * 4u);
2244 if (RESP_NEED > resp_cap)
2245 {
2246 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2247 Memory::FastCopy(&resp[1], &done, sizeof(done));
2248 resp[3] = xresp;
2249 out_len = resp_off;
2250 return ErrorCode::OK;
2251 }
2252
2253 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2254 ErrorCode ec = ErrorCode::OK;
2255
2256 // 先发第一笔 AP read(posted),其 returned posted data 丢弃
2257 uint32_t dummy_posted = 0u;
2258 ec = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
2259 xresp = MapAckToDapResp(ack);
2260 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2261 {
2262 goto out_ap_read; // NOLINT
2263 }
2264 if (ec != ErrorCode::OK)
2265 {
2266 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2267 goto out_ap_read; // NOLINT
2268 }
2269
2270 // i=1..COUNT-1:每次 AP read 返回上一笔数据
2271 for (uint32_t i = 1; i < count; ++i)
2272 {
2273 uint32_t posted_prev = 0u;
2274 ec = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
2275 const uint8_t CUR = MapAckToDapResp(ack);
2276
2277 if (ack != LibXR::Debug::SwdProtocol::Ack::OK || ec != ErrorCode::OK)
2278 {
2279 // 当前失败:尽量用 RDBUFF 把上一笔补齐(done 会更准确)
2280 if (resp_off + 4u <= resp_cap)
2281 {
2282 uint32_t last = 0u;
2283 LibXR::Debug::SwdProtocol::Ack ack2 =
2284 LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2285 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2286 const uint8_t V2 = MapAckToDapResp(ack2);
2287
2288 if (V2 == 1u && EC2 == ErrorCode::OK)
2289 {
2290 Memory::FastCopy(&resp[resp_off], &last, sizeof(last));
2291 resp_off = static_cast<uint16_t>(resp_off + 4u);
2292 done = static_cast<uint16_t>(i); // 成功补齐了第 i-1 笔 => done=i
2293 }
2294 else
2295 {
2296 // 更早的 pending 失败:以它为准
2297 xresp = V2;
2298 if (EC2 != ErrorCode::OK)
2299 {
2300 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2301 }
2302 goto out_ap_read; // NOLINT
2303 }
2304 }
2305
2306 // pending 已补齐:保留“当前失败”
2307 xresp = CUR;
2308 if (ec != ErrorCode::OK)
2309 {
2310 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2311 }
2312 goto out_ap_read; // NOLINT
2313 }
2314
2315 // 当前成功:posted_prev 是上一笔(i-1)的数据
2316 Memory::FastCopy(&resp[resp_off], &posted_prev, sizeof(posted_prev));
2317 resp_off = static_cast<uint16_t>(resp_off + 4u);
2318 done = static_cast<uint16_t>(i); // 已完成 i 笔(0..i-1)
2319 xresp = CUR;
2320 }
2321
2322 // 收尾:读一次 RDBUFF 取回最后一笔
2323 {
2324 uint32_t last = 0u;
2325 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2326 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2327 const uint8_t V2 = MapAckToDapResp(ack2);
2328
2329 xresp = V2;
2330 if (V2 != 1u)
2331 {
2332 goto out_ap_read; // NOLINT
2333 }
2334 if (EC2 != ErrorCode::OK)
2335 {
2336 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2337 goto out_ap_read; // NOLINT
2338 }
2339
2340 Memory::FastCopy(&resp[resp_off], &last, sizeof(last));
2341 resp_off = static_cast<uint16_t>(resp_off + 4u);
2342 done = count;
2343 }
2344
2345 out_ap_read:
2346 Memory::FastCopy(&resp[1], &done, sizeof(done));
2347 resp[3] = xresp;
2348 out_len = resp_off;
2349 return ErrorCode::OK;
2350 }
2351 }
2352
2353 private:
2354 // ============================================================================
2355 // Reset helpers
2356 // ============================================================================
2357
2358 void DriveReset(bool release)
2359 {
2360 last_nreset_level_high_ = release;
2361
2362 // Update shadow regardless of whether GPIO exists
2363 if (release)
2364 {
2365 swj_shadow_ |= LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET;
2366 }
2367 else
2368 {
2369 swj_shadow_ = static_cast<uint8_t>(
2370 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET));
2371 }
2372
2373 if (nreset_gpio_ != nullptr)
2374 {
2375 (void)nreset_gpio_->Write(release);
2376 }
2377 }
2378
2379 void DelayUsIfAllowed(bool /*in_isr*/, uint32_t us)
2380 {
2382 }
2383
2384 private:
2385 static constexpr uint16_t DEFAULT_DAP_PACKET_SIZE = 64u;
2386 static constexpr uint8_t PACKET_COUNT_ADVERTISED = 2u;
2387 static constexpr uint8_t MAX_OUTSTANDING_RESPONSES = PACKET_COUNT_ADVERTISED;
2388 static constexpr uint16_t MAX_DAP_PACKET_SIZE = 512u; // USB HS bulk max packet size.
2389 static constexpr uint16_t RESP_SLOT_SIZE = MAX_DAP_PACKET_SIZE;
2390 static constexpr uint8_t RESP_QUEUE_DEPTH = PACKET_COUNT_ADVERTISED;
2391 static_assert(RESP_SLOT_SIZE >= DEFAULT_DAP_PACKET_SIZE,
2392 "RESP_SLOT_SIZE must cover FS bulk packet size");
2393 static_assert((RESP_QUEUE_DEPTH & (RESP_QUEUE_DEPTH - 1u)) == 0u,
2394 "Response queue depth must be power-of-two");
2395
2396 static constexpr uint8_t WINUSB_VENDOR_CODE =
2397 0x20;
2398
2399 // REG_MULTI_SZ: "<GUID>\0\0" (UTF-16LE). GUID_STR_UTF16_BYTES should already include
2400 // the first UTF-16 NUL.
2401 static constexpr uint16_t GUID_MULTI_SZ_UTF_16_BYTES =
2402 static_cast<uint16_t>(LibXR::USB::WinUsbMsOs20::GUID_STR_UTF16_BYTES +
2403 2);
2404
2406 {
2407 uint16_t len = 0u;
2408 uint8_t payload[RESP_SLOT_SIZE] = {};
2409 };
2410
2411 ResponseSlot resp_q_[RESP_QUEUE_DEPTH] = {};
2412 uint8_t resp_q_head_ = 0u;
2413 uint8_t resp_q_tail_ = 0u;
2414 uint8_t resp_q_count_ = 0u;
2415 bool deferred_in_resp_valid_ = false;
2416 uint16_t deferred_in_resp_len_ = 0u;
2417
2418#pragma pack(push, 1)
2447#pragma pack(pop)
2448
2449 private:
2450 SwdPort& swd_;
2451
2453
2454 uint8_t swj_shadow_ = static_cast<uint8_t>(
2455 DapLinkV2Def::DAP_SWJ_SWDIO_TMS |
2456 DapLinkV2Def::DAP_SWJ_NRESET);
2457
2459 true;
2460
2463 "XRobot", "DAPLinkV2", "00000001", "2.0.0", "XRUSB",
2464 "XRDAP", "XRobot", "DAP_DEMO", "0.1.0"};
2465
2466 uint32_t swj_clock_hz_ = 1000000u;
2467
2470
2473
2474 bool inited_ = false;
2475 uint8_t interface_num_ = 0;
2476
2477#pragma pack(push, 1)
2488#pragma pack(pop)
2489
2490 private:
2494
2495 uint32_t match_mask_ = 0xFFFFFFFFu;
2496
2499
2502};
2503
2504} // namespace LibXR::USB
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:150
static Callback Create(FunType fun, ArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:167
常量原始数据封装类。 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.
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
Definition libxr_mem.cpp:3
原始数据封装类。 A class for encapsulating raw data.
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
Definition timebase.hpp:49
static void DelayMicroseconds(uint32_t us)
微秒级延时 / Delay in microseconds
Definition timebase.hpp:69
BOS 能力接口 / BOS capability interface.
Definition bos.hpp:56
void SetData(RawData data)
设置内部数据缓存 / Set internal data cache
Definition desc_cfg.hpp:194
USB 设备类接口基类 / USB device class interface base.
Definition dev_core.hpp:26
USB 端点基类 / USB Endpoint base class.
Definition ep.hpp:23
EPNumber
端点号 Endpoint number
Definition ep.hpp:41
@ EP_AUTO
自动分配端点号 / Auto allocate
uint8_t GetAddress() const
获取端点地址(方向 + 号) / Get endpoint address (dir + num)
Definition ep.hpp:194
@ 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
@ BULK
批量端点 / Bulk
virtual void Close()=0
关闭端点 / Close endpoint
uint16_t MaxPacketSize() const
获取最大包长 / Get max packet size
Definition ep.hpp:225
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:23
ErrorCode Get(Endpoint *&ep_info, Endpoint::Direction direction, Endpoint::EPNumber ep_num=Endpoint::EPNumber::EP_AUTO)
分配端点 / Allocate endpoint
Definition ep_pool.cpp:11
ErrorCode Release(Endpoint *ep_info)
回收端点 / Release endpoint
Definition ep_pool.cpp:37
LibXR 命名空间
Definition ch32_can.hpp:14
端点描述符(7 字节)/ Endpoint descriptor (7 bytes)
Definition desc_cfg.hpp:92
接口描述符(9 字节)/ Interface descriptor (9 bytes)
Definition desc_cfg.hpp:76