7#include "daplink_v1_def.hpp"
8#include "debug/jtag_dp.hpp"
9#include "debug/swd.hpp"
12#include "libxr_def.hpp"
13#include "libxr_mem.hpp"
14#include "libxr_type.hpp"
15#include "timebase.hpp"
19#ifndef LIBXR_USB_DAPLINK_V1_BUILD_CONFIG_DEFINED
20#define LIBXR_USB_DAPLINK_V1_BUILD_CONFIG_DEFINED
21namespace DapLinkV1BuildConfig
23static constexpr bool kEnableJtag =
true;
27static constexpr uint8_t DAPLINK_V1_REPORT_DESC[] = {
46template <
typename SwdPort>
48 :
public HID<sizeof(DAPLINK_V1_REPORT_DESC), DapLinkV1Def::MAX_REQUEST_SIZE,
49 DapLinkV1Def::MAX_RESPONSE_SIZE>
52 static constexpr bool JTAG_ENABLED = DapLinkV1BuildConfig::kEnableJtag;
53 static constexpr const char* DEFAULT_INTERFACE_STRING =
"CMSIS-DAP";
56 const char* vendor =
nullptr;
57 const char* product =
nullptr;
58 const char* serial =
nullptr;
59 const char* firmware_ver =
nullptr;
61 const char* device_vendor =
nullptr;
62 const char* device_name =
nullptr;
63 const char* board_vendor =
nullptr;
64 const char* board_name =
nullptr;
65 const char* product_fw_ver =
nullptr;
69 SwdPort& swd_link,
LibXR::GPIO* nreset_gpio =
nullptr);
79 bool IsInited()
const;
86 bool in_isr)
override;
93 static void OnDataOutCompleteStatic(
bool in_isr,
DapLinkV1Class* self,
95 static void OnDataInCompleteStatic(
bool in_isr,
DapLinkV1Class* self,
98 void ArmOutTransferIfIdle();
100 ErrorCode ProcessOneCommand(
bool in_isr,
const uint8_t* req, uint16_t req_len,
101 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
102 void BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
104 ErrorCode HandleInfo(
bool in_isr,
const uint8_t* req, uint16_t req_len, uint8_t* resp,
105 uint16_t resp_cap, uint16_t& out_len);
106 ErrorCode HandleHostStatus(
bool in_isr,
const uint8_t* req, uint16_t req_len,
107 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
108 ErrorCode HandleConnect(
bool in_isr,
const uint8_t* req, uint16_t req_len,
109 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
110 ErrorCode HandleDisconnect(
bool in_isr,
const uint8_t* req, uint16_t req_len,
111 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
112 ErrorCode HandleTransferConfigure(
bool in_isr,
const uint8_t* req, uint16_t req_len,
113 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
114 ErrorCode HandleTransfer(
bool in_isr,
const uint8_t* req, uint16_t req_len,
115 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
116 ErrorCode HandleTransferBlock(
bool in_isr,
const uint8_t* req, uint16_t req_len,
117 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
118 ErrorCode HandleTransferAbort(
bool in_isr,
const uint8_t* req, uint16_t req_len,
119 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
120 ErrorCode HandleWriteABORT(
bool in_isr,
const uint8_t* req, uint16_t req_len,
121 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
122 ErrorCode HandleDelay(
bool in_isr,
const uint8_t* req, uint16_t req_len, uint8_t* resp,
123 uint16_t resp_cap, uint16_t& out_len);
124 ErrorCode HandleResetTarget(
bool in_isr,
const uint8_t* req, uint16_t req_len,
125 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
126 ErrorCode HandleSWJPins(
bool in_isr,
const uint8_t* req, uint16_t req_len,
127 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
128 ErrorCode HandleSWJClock(
bool in_isr,
const uint8_t* req, uint16_t req_len,
129 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
130 ErrorCode HandleSWJSequence(
bool in_isr,
const uint8_t* req, uint16_t req_len,
131 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
132 ErrorCode HandleSWDConfigure(
bool in_isr,
const uint8_t* req, uint16_t req_len,
133 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
134 ErrorCode HandleSWDSequence(
bool in_isr,
const uint8_t* req, uint16_t req_len,
135 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
136 ErrorCode HandleJTAGSequence(
bool in_isr,
const uint8_t* req, uint16_t req_len,
137 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
138 ErrorCode HandleJTAGConfigure(
bool in_isr,
const uint8_t* req, uint16_t req_len,
139 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
140 ErrorCode HandleJTAGIdCode(
bool in_isr,
const uint8_t* req, uint16_t req_len,
141 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
142 ErrorCode HandleQueueCommands(
bool in_isr,
const uint8_t* req, uint16_t req_len,
143 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
144 ErrorCode HandleExecuteCommands(
bool in_isr,
const uint8_t* req, uint16_t req_len,
145 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
147 ErrorCode BuildInfoStringResponse(uint8_t cmd,
const char* str, uint8_t* resp,
148 uint16_t resp_cap, uint16_t& out_len);
149 ErrorCode BuildInfoU8Response(uint8_t cmd, uint8_t val, uint8_t* resp,
150 uint16_t resp_cap, uint16_t& out_len);
151 ErrorCode BuildInfoU16Response(uint8_t cmd, uint16_t val, uint8_t* resp,
152 uint16_t resp_cap, uint16_t& out_len);
153 ErrorCode BuildInfoU32Response(uint8_t cmd, uint32_t val, uint8_t* resp,
154 uint16_t resp_cap, uint16_t& out_len);
156 uint8_t MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack)
const;
157 uint8_t MapAckToDapResp(LibXR::Debug::JtagProtocol::Ack ack)
const;
158 ErrorCode HandleJtagTransfer(
bool in_isr,
const uint8_t* req, uint16_t req_len,
159 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
160 ErrorCode HandleJtagTransferBlock(
bool in_isr,
const uint8_t* req, uint16_t req_len,
161 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
162 ErrorCode HandleJtagWriteAbort(
bool in_isr,
const uint8_t* req, uint16_t req_len,
163 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
164 void SetTransferAbortFlag(
bool on);
166 void DriveReset(
bool release);
167 void DelayUsIfAllowed(
bool in_isr, uint32_t us);
170 template <
typename E>
171 static constexpr uint8_t to_u8(E e)
173 return static_cast<uint8_t
>(e);
176 static constexpr uint8_t DAP_OK = 0x00u;
177 static constexpr uint8_t DAP_ERROR = 0xFFu;
179 static inline ErrorCode build_unknown_cmd_response(uint8_t* resp, uint16_t cap,
182 if (!resp || cap < 1u)
192 static inline ErrorCode build_cmd_status_response(uint8_t cmd, uint8_t status,
193 uint8_t* resp, uint16_t cap,
196 if (!resp || cap < 2u)
207 static constexpr uint16_t MAX_REQ = DapLinkV1Def::MAX_REQUEST_SIZE;
208 static constexpr uint16_t MAX_RESP = DapLinkV1Def::MAX_RESPONSE_SIZE;
209 static constexpr uint8_t JTAG_MAX_DEVICES = 16u;
214 uint8_t jtag_ir_len_[JTAG_MAX_DEVICES] = {};
217 uint8_t swj_shadow_ =
static_cast<uint8_t
>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
218 DapLinkV1Def::DAP_SWJ_NRESET);
219 bool last_nreset_level_high_ =
true;
222 InfoStrings info_{
"XRobot",
"DAPLinkV1",
"00000001",
"1.0.0",
"XRUSB",
223 "XRDAP",
"XRobot",
"DAP_DEMO",
"0.1.0"};
225 uint32_t swj_clock_hz_ = 1000000u;
226 uint32_t match_mask_ = 0xFFFFFFFFu;
228 Endpoint* ep_in_ =
nullptr;
229 Endpoint* ep_out_ =
nullptr;
236 bool inited_ =
false;
239template <
typename SwdPort>
243 : HID(in_ep_num, out_ep_num, true, 1, 1, DEFAULT_INTERFACE_STRING),
245 nreset_gpio_(nreset_gpio)
247 if constexpr (JTAG_ENABLED)
249 jtag_chain_.ir_length = jtag_ir_len_;
250 jtag_chain_.count = 0u;
251 jtag_chain_.index = 0u;
253 (void)swd_.SetClockHz(swj_clock_hz_);
256template <
typename SwdPort>
257void DapLinkV1Class<SwdPort>::SetInfoStrings(
const InfoStrings& info)
262template <
typename SwdPort>
265 if constexpr (JTAG_ENABLED)
275template <
typename SwdPort>
281template <
typename SwdPort>
282bool DapLinkV1Class<SwdPort>::IsInited()
const
287template <
typename SwdPort>
296template <
typename SwdPort>
299 return ConstRawData{DAPLINK_V1_REPORT_DESC,
sizeof(DAPLINK_V1_REPORT_DESC)};
302template <
typename SwdPort>
304 uint8_t start_itf_num,
bool in_isr)
311 if (ep_in_ !=
nullptr)
319 if (ep_out_ !=
nullptr)
328 match_mask_ = 0xFFFFFFFFu;
331 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
334 swj_clock_hz_ = 1000000u;
335 (void)swd_.SetClockHz(swj_clock_hz_);
336 if constexpr (JTAG_ENABLED)
338 if (jtag_ !=
nullptr)
344 if constexpr (JTAG_ENABLED)
346 jtag_chain_.
count = 0u;
347 jtag_chain_.
index = 0u;
355 last_nreset_level_high_ =
true;
356 swj_shadow_ =
static_cast<uint8_t
>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
357 DapLinkV1Def::DAP_SWJ_NRESET);
359 ArmOutTransferIfIdle();
362template <
typename SwdPort>
367 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
376 if constexpr (JTAG_ENABLED)
378 if (jtag_ !=
nullptr)
384 last_nreset_level_high_ =
true;
385 swj_shadow_ =
static_cast<uint8_t
>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
386 DapLinkV1Def::DAP_SWJ_NRESET);
389template <
typename SwdPort>
393 if (self && self->inited_)
395 self->OnDataOutComplete(in_isr, data);
399template <
typename SwdPort>
400void DapLinkV1Class<SwdPort>::OnDataInCompleteStatic(
bool in_isr, DapLinkV1Class* self,
403 if (self && self->inited_)
405 self->OnDataInComplete(in_isr, data);
409template <
typename SwdPort>
412 if (!inited_ || !ep_in_ || !ep_out_)
417 const auto* REQ =
static_cast<const uint8_t*
>(data.
addr_);
418 const uint16_t REQ_LEN =
static_cast<uint16_t
>(data.
size_);
421 const uint16_t RESP_CAP =
static_cast<uint16_t
>(tx_buff.size_);
422 const uint16_t TX_LEN = (RESP_CAP < MAX_RESP) ? RESP_CAP : MAX_RESP;
426 ArmOutTransferIfIdle();
430 uint16_t out_len = 0u;
431 auto ans = ProcessOneCommand(
432 in_isr, REQ, REQ_LEN,
reinterpret_cast<uint8_t*
>(tx_buff.addr_), RESP_CAP, out_len);
447template <
typename SwdPort>
460 ArmOutTransferIfIdle();
463template <
typename SwdPort>
464void DapLinkV1Class<SwdPort>::ArmOutTransferIfIdle()
466 if (!inited_ || !ep_out_)
479template <
typename SwdPort>
480ErrorCode DapLinkV1Class<SwdPort>::ProcessOneCommand(
bool in_isr,
const uint8_t* req,
481 uint16_t req_len, uint8_t* resp,
482 uint16_t resp_cap, uint16_t& out_len)
486 if (!req || !resp || req_len < 1u || resp_cap < 1u)
488 if (resp && resp_cap >= 1u)
490 BuildNotSupportResponse(resp, resp_cap, out_len);
495 const uint8_t CMD = req[0];
499 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::INFO):
500 return HandleInfo(in_isr, req, req_len, resp, resp_cap, out_len);
501 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS):
502 return HandleHostStatus(in_isr, req, req_len, resp, resp_cap, out_len);
503 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT):
504 return HandleConnect(in_isr, req, req_len, resp, resp_cap, out_len);
505 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT):
506 return HandleDisconnect(in_isr, req, req_len, resp, resp_cap, out_len);
507 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE):
508 return HandleTransferConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
509 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER):
510 return HandleTransfer(in_isr, req, req_len, resp, resp_cap, out_len);
511 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK):
512 return HandleTransferBlock(in_isr, req, req_len, resp, resp_cap, out_len);
513 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT):
514 return HandleTransferAbort(in_isr, req, req_len, resp, resp_cap, out_len);
515 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT):
516 return HandleWriteABORT(in_isr, req, req_len, resp, resp_cap, out_len);
517 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::DELAY):
518 return HandleDelay(in_isr, req, req_len, resp, resp_cap, out_len);
519 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET):
520 return HandleResetTarget(in_isr, req, req_len, resp, resp_cap, out_len);
521 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS):
522 return HandleSWJPins(in_isr, req, req_len, resp, resp_cap, out_len);
523 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK):
524 return HandleSWJClock(in_isr, req, req_len, resp, resp_cap, out_len);
525 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE):
526 return HandleSWJSequence(in_isr, req, req_len, resp, resp_cap, out_len);
527 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE):
528 return HandleSWDConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
529 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE):
530 return HandleSWDSequence(in_isr, req, req_len, resp, resp_cap, out_len);
531 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_SEQUENCE):
532 if constexpr (JTAG_ENABLED)
534 return HandleJTAGSequence(in_isr, req, req_len, resp, resp_cap, out_len);
536 BuildNotSupportResponse(resp, resp_cap, out_len);
538 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_CONFIGURE):
539 if constexpr (JTAG_ENABLED)
541 return HandleJTAGConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
543 BuildNotSupportResponse(resp, resp_cap, out_len);
545 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_IDCODE):
546 if constexpr (JTAG_ENABLED)
548 return HandleJTAGIdCode(in_isr, req, req_len, resp, resp_cap, out_len);
550 BuildNotSupportResponse(resp, resp_cap, out_len);
552 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::QUEUE_COMMANDS):
553 return HandleQueueCommands(in_isr, req, req_len, resp, resp_cap, out_len);
554 case to_u8(LibXR::USB::DapLinkV1Def::CommandId::EXECUTE_COMMANDS):
555 return HandleExecuteCommands(in_isr, req, req_len, resp, resp_cap, out_len);
557 (void)build_unknown_cmd_response(resp, resp_cap, out_len);
562template <
typename SwdPort>
563void DapLinkV1Class<SwdPort>::BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap,
566 if (!resp || resp_cap < 1u)
575template <
typename SwdPort>
576ErrorCode DapLinkV1Class<SwdPort>::HandleInfo(
bool ,
const uint8_t* req,
577 uint16_t req_len, uint8_t* resp,
578 uint16_t resp_cap, uint16_t& out_len)
582 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
588 const uint8_t INFO_ID = req[1];
590 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
594 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::VENDOR):
595 return BuildInfoStringResponse(resp[0], info_.vendor, resp, resp_cap, out_len);
596 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT):
597 return BuildInfoStringResponse(resp[0], info_.product, resp, resp_cap, out_len);
598 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::SERIAL_NUMBER):
599 return BuildInfoStringResponse(resp[0], info_.serial, resp, resp_cap, out_len);
600 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::FIRMWARE_VERSION):
601 return BuildInfoStringResponse(resp[0], info_.firmware_ver, resp, resp_cap,
603 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_VENDOR):
604 return BuildInfoStringResponse(resp[0], info_.device_vendor, resp, resp_cap,
606 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_NAME):
607 return BuildInfoStringResponse(resp[0], info_.device_name, resp, resp_cap, out_len);
608 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_VENDOR):
609 return BuildInfoStringResponse(resp[0], info_.board_vendor, resp, resp_cap,
611 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_NAME):
612 return BuildInfoStringResponse(resp[0], info_.board_name, resp, resp_cap, out_len);
613 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT_FIRMWARE_VERSION):
614 return BuildInfoStringResponse(resp[0], info_.product_fw_ver, resp, resp_cap,
616 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::CAPABILITIES):
619 if constexpr (JTAG_ENABLED)
621 if (jtag_ !=
nullptr)
626 return BuildInfoU8Response(resp[0], caps, resp, resp_cap, out_len);
628 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_COUNT):
629 return BuildInfoU8Response(resp[0], 1, resp, resp_cap, out_len);
630 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_SIZE):
631 return BuildInfoU16Response(resp[0], MAX_RESP, resp, resp_cap, out_len);
632 case to_u8(LibXR::USB::DapLinkV1Def::InfoId::TIMESTAMP_CLOCK):
633 return BuildInfoU32Response(resp[0], 1000000U, resp, resp_cap, out_len);
641template <
typename SwdPort>
642ErrorCode DapLinkV1Class<SwdPort>::BuildInfoStringResponse(uint8_t cmd,
const char* str,
656 const size_t N_WITH_NUL = std::strlen(str) + 1;
657 const size_t MAX_PAYLOAD = (resp_cap >= 2u) ? (resp_cap - 2u) : 0u;
658 if (MAX_PAYLOAD == 0u)
664 const size_t COPY_N = (N_WITH_NUL > MAX_PAYLOAD) ? MAX_PAYLOAD : N_WITH_NUL;
666 resp[1] =
static_cast<uint8_t
>(COPY_N);
667 out_len =
static_cast<uint16_t
>(COPY_N + 2u);
671template <
typename SwdPort>
672ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU8Response(uint8_t cmd, uint8_t val,
673 uint8_t* resp, uint16_t resp_cap,
688template <
typename SwdPort>
689ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU16Response(uint8_t cmd, uint16_t val,
690 uint8_t* resp, uint16_t resp_cap,
705template <
typename SwdPort>
706ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU32Response(uint8_t cmd, uint32_t val,
707 uint8_t* resp, uint16_t resp_cap,
722template <
typename SwdPort>
723ErrorCode DapLinkV1Class<SwdPort>::HandleHostStatus(
bool ,
725 uint16_t , uint8_t* resp,
726 uint16_t resp_cap, uint16_t& out_len)
733 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS);
734 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
739template <
typename SwdPort>
740ErrorCode DapLinkV1Class<SwdPort>::HandleConnect(
bool ,
const uint8_t* req,
741 uint16_t req_len, uint8_t* resp,
742 uint16_t resp_cap, uint16_t& out_len)
750 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT);
760 port = to_u8(LibXR::USB::DapLinkV1Def::Port::SWD);
763 if (port == to_u8(LibXR::USB::DapLinkV1Def::Port::SWD))
765 (void)swd_.EnterSwd();
766 (void)swd_.SetClockHz(swj_clock_hz_);
768 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::SWD;
771 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::SWD);
773 else if (port == to_u8(LibXR::USB::DapLinkV1Def::Port::JTAG))
775 if constexpr (!JTAG_ENABLED)
777 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
781 if (jtag_ ==
nullptr)
783 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
788 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::JTAG;
790 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::JTAG);
796 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
803template <
typename SwdPort>
804ErrorCode DapLinkV1Class<SwdPort>::HandleDisconnect(
bool ,
806 uint16_t , uint8_t* resp,
807 uint16_t resp_cap, uint16_t& out_len)
816 dap_state_.
debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
819 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT);
820 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
825template <
typename SwdPort>
826ErrorCode DapLinkV1Class<SwdPort>::HandleTransferConfigure(
827 bool ,
const uint8_t* req, uint16_t req_len, uint8_t* resp,
828 uint16_t resp_cap, uint16_t& out_len)
836 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE);
840 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
845 const uint8_t IDLE = req[1];
847 uint16_t wait_retry = 0u;
848 uint16_t match_retry = 0u;
859 swd_.SetTransferPolicy(pol);
861 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
866template <
typename SwdPort>
867ErrorCode DapLinkV1Class<SwdPort>::HandleTransferAbort(
bool ,
870 uint8_t* resp, uint16_t resp_cap,
879 SetTransferAbortFlag(
true);
881 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT);
882 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
887template <
typename SwdPort>
888ErrorCode DapLinkV1Class<SwdPort>::HandleWriteABORT(
bool ,
const uint8_t* req,
889 uint16_t req_len, uint8_t* resp,
890 uint16_t resp_cap, uint16_t& out_len)
898 if constexpr (JTAG_ENABLED)
900 if (dap_state_.
debug_port == LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
902 return HandleJtagWriteAbort(
false, req, req_len, resp, resp_cap, out_len);
906 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT);
910 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
918 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
919 const ErrorCode EC = swd_.WriteAbortTxn(flags, ack);
920 resp[1] = (EC ==
ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
921 ? to_u8(LibXR::USB::DapLinkV1Def::Status::OK)
922 : to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
928template <
typename SwdPort>
929ErrorCode DapLinkV1Class<SwdPort>::HandleDelay(
bool ,
const uint8_t* req,
930 uint16_t req_len, uint8_t* resp,
931 uint16_t resp_cap, uint16_t& out_len)
939 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::DELAY);
943 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
953 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
958template <
typename SwdPort>
959ErrorCode DapLinkV1Class<SwdPort>::HandleResetTarget(
bool in_isr,
const uint8_t* ,
960 uint16_t , uint8_t* resp,
961 uint16_t resp_cap, uint16_t& out_len)
963 if (!resp || resp_cap < 3u)
969 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET);
971 uint8_t execute = 0u;
972 if (nreset_gpio_ !=
nullptr)
975 DelayUsIfAllowed(in_isr, 1000u);
977 DelayUsIfAllowed(in_isr, 1000u);
987template <
typename SwdPort>
988ErrorCode DapLinkV1Class<SwdPort>::HandleSWJPins(
bool ,
const uint8_t* req,
989 uint16_t req_len, uint8_t* resp,
990 uint16_t resp_cap, uint16_t& out_len)
992 if (!resp || resp_cap < 2u)
998 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS);
1000 if (!req || req_len < 7u)
1007 const uint8_t PIN_OUT = req[1];
1008 const uint8_t PIN_SEL = req[2];
1010 uint32_t wait_us = 0u;
1013 swj_shadow_ =
static_cast<uint8_t
>((swj_shadow_ &
static_cast<uint8_t
>(~PIN_SEL)) |
1014 (PIN_OUT & PIN_SEL));
1016 if ((PIN_SEL & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u)
1018 const bool LEVEL_HIGH = ((PIN_OUT & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u);
1019 DriveReset(LEVEL_HIGH);
1022 auto read_pins = [&]() -> uint8_t
1024 uint8_t pin_in = swj_shadow_;
1026 if (nreset_gpio_ !=
nullptr)
1028 if (nreset_gpio_->
Read())
1030 pin_in |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
1034 pin_in =
static_cast<uint8_t
>(
1035 pin_in &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
1042 uint8_t pin_in = 0u;
1043 if (wait_us == 0u || PIN_SEL == 0u)
1045 pin_in = read_pins();
1050 const uint8_t EXPECT =
static_cast<uint8_t
>(PIN_OUT & PIN_SEL);
1054 pin_in = read_pins();
1055 if ((pin_in & PIN_SEL) == EXPECT)
1068template <
typename SwdPort>
1069ErrorCode DapLinkV1Class<SwdPort>::HandleSWJClock(
bool ,
const uint8_t* req,
1070 uint16_t req_len, uint8_t* resp,
1071 uint16_t resp_cap, uint16_t& out_len)
1079 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK);
1083 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1092 (void)swd_.SetClockHz(hz);
1093 if constexpr (JTAG_ENABLED)
1095 if (jtag_ !=
nullptr)
1101 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
1106template <
typename SwdPort>
1107ErrorCode DapLinkV1Class<SwdPort>::HandleSWJSequence(
bool ,
const uint8_t* req,
1108 uint16_t req_len, uint8_t* resp,
1109 uint16_t resp_cap, uint16_t& out_len)
1111 if (!resp || resp_cap < 2u)
1117 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE);
1118 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
1121 if (!req || req_len < 2u)
1123 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1127 uint32_t bit_count = req[1];
1128 if (bit_count == 0u)
1133 const uint32_t BYTE_COUNT = (bit_count + 7u) / 8u;
1134 if (req_len < (2u + BYTE_COUNT))
1136 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1140 const uint8_t* DATA = &req[2];
1141 const ErrorCode EC = swd_.SeqWriteBits(bit_count, DATA);
1144 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1148 swj_shadow_ =
static_cast<uint8_t
>(
1149 swj_shadow_ &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWCLK_TCK));
1151 bool last_swdio =
false;
1152 if (bit_count != 0u)
1154 const uint32_t LAST_I = bit_count - 1u;
1155 last_swdio = (((DATA[LAST_I / 8u] >> (LAST_I & 7u)) & 0x01u) != 0u);
1160 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS;
1164 swj_shadow_ =
static_cast<uint8_t
>(
1165 swj_shadow_ &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS));
1171template <
typename SwdPort>
1172ErrorCode DapLinkV1Class<SwdPort>::HandleSWDConfigure(
bool ,
1174 uint16_t , uint8_t* resp,
1184 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE);
1185 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
1190template <
typename SwdPort>
1191ErrorCode DapLinkV1Class<SwdPort>::HandleSWDSequence(
bool ,
const uint8_t* req,
1192 uint16_t req_len, uint8_t* resp,
1193 uint16_t resp_cap, uint16_t& out_len)
1195 if (!req || !resp || resp_cap < 2u)
1201 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE);
1207 resp[1] = DAP_ERROR;
1212 const uint8_t SEQ_CNT = req[1];
1213 uint16_t req_off = 2u;
1214 uint16_t resp_off = 2u;
1216 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1218 if (req_off >= req_len)
1220 resp[1] = DAP_ERROR;
1225 const uint8_t INFO = req[req_off++];
1226 uint32_t cycles =
static_cast<uint32_t
>(INFO & 0x3Fu);
1232 const bool MODE_IN = ((INFO & 0x80u) != 0u);
1233 const uint16_t BYTES =
static_cast<uint16_t
>((cycles + 7u) / 8u);
1237 if (req_off + BYTES > req_len)
1239 resp[1] = DAP_ERROR;
1244 const uint8_t* DATA = &req[req_off];
1245 req_off =
static_cast<uint16_t
>(req_off + BYTES);
1247 const ErrorCode EC = swd_.SeqWriteBits(cycles, DATA);
1250 resp[1] = DAP_ERROR;
1257 if (resp_off + BYTES > resp_cap)
1259 resp[1] = DAP_ERROR;
1265 const ErrorCode EC = swd_.SeqReadBits(cycles, &resp[resp_off]);
1268 resp[1] = DAP_ERROR;
1273 resp_off =
static_cast<uint16_t
>(resp_off + BYTES);
1281template <
typename SwdPort>
1282ErrorCode DapLinkV1Class<SwdPort>::HandleJTAGSequence(
bool ,
const uint8_t* req,
1283 uint16_t req_len, uint8_t* resp,
1287 if (!req || !resp || resp_cap < 2u)
1293 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_SEQUENCE);
1297 if (jtag_ ==
nullptr)
1299 resp[1] = DAP_ERROR;
1305 resp[1] = DAP_ERROR;
1309 const uint8_t SEQ_CNT = req[1];
1310 uint16_t req_off = 2u;
1311 uint16_t resp_off = 2u;
1313 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1315 if (req_off >= req_len)
1317 resp[1] = DAP_ERROR;
1322 const uint8_t INFO = req[req_off++];
1323 uint32_t cycles =
static_cast<uint32_t
>(INFO & 0x3Fu);
1329 const bool TMS = ((INFO & LibXR::Debug::JtagProtocol::JTAG_SEQUENCE_TMS) != 0u);
1330 const bool CAPTURE = ((INFO & LibXR::Debug::JtagProtocol::JTAG_SEQUENCE_TDO) != 0u);
1331 const uint16_t BYTES =
static_cast<uint16_t
>((cycles + 7u) / 8u);
1333 if (req_off + BYTES > req_len)
1335 resp[1] = DAP_ERROR;
1340 if (CAPTURE && (resp_off + BYTES > resp_cap))
1342 resp[1] = DAP_ERROR;
1347 const uint8_t* DATA = &req[req_off];
1348 uint8_t* OUT = CAPTURE ? &resp[resp_off] :
nullptr;
1357 resp[1] = DAP_ERROR;
1362 req_off =
static_cast<uint16_t
>(req_off + BYTES);
1365 resp_off =
static_cast<uint16_t
>(resp_off + BYTES);
1373template <
typename SwdPort>
1374ErrorCode DapLinkV1Class<SwdPort>::HandleJTAGConfigure(
bool ,
1376 uint16_t req_len, uint8_t* resp,
1380 if (!req || !resp || resp_cap < 2u)
1386 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_CONFIGURE);
1390 if (jtag_ ==
nullptr)
1392 resp[1] = DAP_ERROR;
1398 resp[1] = DAP_ERROR;
1402 const uint8_t COUNT = req[1];
1403 if (COUNT > JTAG_MAX_DEVICES || req_len <
static_cast<uint16_t
>(2u + COUNT))
1405 resp[1] = DAP_ERROR;
1412 for (uint32_t i = 0; i < COUNT; ++i)
1414 const uint8_t LEN = req[
static_cast<uint16_t
>(2u + i)];
1415 jtag_ir_len_[i] = LEN;
1419 jtag_chain_.
count = COUNT;
1422 jtag_chain_.
index = 0u;
1432template <
typename SwdPort>
1433ErrorCode DapLinkV1Class<SwdPort>::HandleJTAGIdCode(
bool ,
const uint8_t* req,
1434 uint16_t req_len, uint8_t* resp,
1435 uint16_t resp_cap, uint16_t& out_len)
1437 if (!req || !resp || resp_cap < 2u)
1449 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::JTAG_IDCODE);
1450 resp[1] = DAP_ERROR;
1453 if (jtag_ ==
nullptr ||
1454 dap_state_.
debug_port != LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
1464 const uint8_t INDEX = req[1];
1465 if (INDEX >= jtag_chain_.
count)
1470 jtag_chain_.
index = INDEX;
1471 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
1474 uint32_t idcode = 0u;
1477 (idcode == 0u || idcode == 0xFFFF'FFFFu || ((idcode & 0x1u) == 0u)) &&
1478 jtag_ir_len_[INDEX] != 4u)
1480 uint32_t fallback_idcode = 0u;
1481 EC = dp.ReadIdCodeWithIr(0x01u, fallback_idcode);
1486 if (fallback_idcode != 0u && fallback_idcode != 0xFFFF'FFFFu &&
1487 ((fallback_idcode & 0x1u) != 0u))
1489 idcode = fallback_idcode;
1498 resp[2] =
static_cast<uint8_t
>(idcode & 0xFFu);
1499 resp[3] =
static_cast<uint8_t
>((idcode >> 8) & 0xFFu);
1500 resp[4] =
static_cast<uint8_t
>((idcode >> 16) & 0xFFu);
1501 resp[5] =
static_cast<uint8_t
>((idcode >> 24) & 0xFFu);
1506template <
typename SwdPort>
1507ErrorCode DapLinkV1Class<SwdPort>::HandleQueueCommands(
bool ,
1510 uint8_t* resp, uint16_t resp_cap,
1513 return build_cmd_status_response(
1514 to_u8(LibXR::USB::DapLinkV1Def::CommandId::QUEUE_COMMANDS), DAP_ERROR, resp,
1518template <
typename SwdPort>
1519ErrorCode DapLinkV1Class<SwdPort>::HandleExecuteCommands(
bool ,
1522 uint8_t* resp, uint16_t resp_cap,
1525 return build_cmd_status_response(
1526 to_u8(LibXR::USB::DapLinkV1Def::CommandId::EXECUTE_COMMANDS), DAP_ERROR, resp,
1530template <
typename SwdPort>
1531uint8_t DapLinkV1Class<SwdPort>::MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack)
const
1535 case LibXR::Debug::SwdProtocol::Ack::OK:
1537 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1539 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1541 case LibXR::Debug::SwdProtocol::Ack::NO_ACK:
1542 case LibXR::Debug::SwdProtocol::Ack::PROTOCOL:
1548template <
typename SwdPort>
1549uint8_t DapLinkV1Class<SwdPort>::MapAckToDapResp(
1550 LibXR::Debug::JtagProtocol::Ack ack)
const
1554 case LibXR::Debug::JtagProtocol::Ack::OK:
1556 case LibXR::Debug::JtagProtocol::Ack::WAIT:
1558 case LibXR::Debug::JtagProtocol::Ack::FAULT:
1560 case LibXR::Debug::JtagProtocol::Ack::NO_ACK:
1561 case LibXR::Debug::JtagProtocol::Ack::PROTOCOL:
1567template <
typename SwdPort>
1568void DapLinkV1Class<SwdPort>::SetTransferAbortFlag(
bool on)
1573template <
typename SwdPort>
1574ErrorCode DapLinkV1Class<SwdPort>::HandleTransfer(
bool ,
const uint8_t* req,
1575 uint16_t req_len, uint8_t* resp,
1576 uint16_t resp_cap, uint16_t& out_len)
1579 if (!req || !resp || resp_cap < 3u)
1584 if constexpr (JTAG_ENABLED)
1586 if (dap_state_.
debug_port == LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
1588 return HandleJtagTransfer(
false, req, req_len, resp, resp_cap, out_len);
1592 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER);
1595 uint16_t resp_off = 3u;
1599 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1607 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1612 const uint8_t COUNT = req[2];
1613 uint16_t req_off = 3u;
1615 auto ack_to_dap = [&](LibXR::Debug::SwdProtocol::Ack ack) -> uint8_t
1619 case LibXR::Debug::SwdProtocol::Ack::OK:
1620 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1621 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1622 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_WAIT;
1623 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1624 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_FAULT;
1630 auto push_u32 = [&](uint32_t VALUE) ->
bool
1632 if (resp_off + 4u > resp_cap)
1637 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
1641 auto push_timestamp = [&]() ->
bool
1647 auto ensure_space = [&](uint16_t bytes) ->
bool
1648 {
return (resp_off + bytes) <= resp_cap; };
1650 auto bytes_for_read = [&](
bool need_ts) -> uint16_t
1651 {
return static_cast<uint16_t
>(need_ts ? 8u : 4u); };
1653 uint8_t response_count = 0u;
1654 uint8_t response_value = 0u;
1655 bool check_write =
false;
1657 struct PendingApRead
1660 bool need_ts =
false;
1663 auto emit_read_with_ts = [&](
bool need_ts, uint32_t data) ->
bool
1667 if (!push_timestamp())
1672 if (!push_u32(data))
1680 auto complete_pending_by_rdbuff = [&]() ->
bool
1687 if (!ensure_space(bytes_for_read(pending.need_ts)))
1689 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1693 uint32_t rdata = 0u;
1694 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1695 const ErrorCode EC = swd_.DpReadRdbuffTxn(rdata, ack);
1697 const uint8_t V = ack_to_dap(ack);
1698 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1705 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1709 if (!emit_read_with_ts(pending.need_ts, rdata))
1711 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1715 pending.valid =
false;
1716 pending.need_ts =
false;
1717 check_write =
false;
1718 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1722 auto flush_pending_if_any = [&]() ->
bool
1723 {
return pending.valid ? complete_pending_by_rdbuff() : true; };
1725 for (uint32_t i = 0; i < COUNT; ++i)
1727 if (req_off >= req_len)
1729 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1733 const uint8_t RQ = req[req_off++];
1740 const bool MATCH_VALUE =
1741 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
1742 const bool MATCH_MASK =
1743 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK) != 0u);
1745 if (TS && (MATCH_VALUE || MATCH_MASK))
1747 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1751 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1756 if (!flush_pending_if_any())
1761 if (req_off + 4u > req_len)
1763 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1767 uint32_t wdata = 0u;
1769 req_off =
static_cast<uint16_t
>(req_off + 4u);
1773 match_mask_ = wdata;
1774 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1781 EC = swd_.ApWriteTxn(ADDR2B, wdata, ack);
1785 EC = swd_.DpWriteTxn(
static_cast<LibXR::Debug::SwdProtocol::DpWriteReg
>(ADDR2B),
1789 response_value = ack_to_dap(ack);
1790 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1796 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1802 if (!push_timestamp())
1804 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1816 if (!flush_pending_if_any())
1821 if (req_off + 4u > req_len)
1823 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1827 uint32_t match_val = 0u;
1829 req_off =
static_cast<uint16_t
>(req_off + 4u);
1831 uint32_t rdata = 0u;
1833 bool matched =
false;
1839 EC = swd_.ApReadTxn(ADDR2B, rdata, ack);
1840 if (EC ==
ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1842 check_write =
false;
1847 EC = swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
1851 response_value = ack_to_dap(ack);
1852 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1858 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1862 if ((rdata & match_mask_) == (match_val & match_mask_))
1875 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1883 static_cast<uint8_t
>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
1884 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
1888 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1895 if (!flush_pending_if_any())
1900 uint32_t rdata = 0u;
1901 EC = swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
1904 response_value = ack_to_dap(ack);
1905 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1911 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1915 if (!ensure_space(bytes_for_read(TS)))
1917 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1921 if (!emit_read_with_ts(TS, rdata))
1923 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1927 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1933 uint32_t dummy_posted = 0u;
1934 EC = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
1936 response_value = ack_to_dap(ack);
1937 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1943 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1947 pending.valid =
true;
1948 pending.need_ts = TS;
1949 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1953 if (!ensure_space(bytes_for_read(pending.need_ts)))
1955 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1959 uint32_t posted_prev = 0u;
1960 EC = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
1962 const uint8_t CUR_V = ack_to_dap(ack);
1963 if (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK || EC !=
ErrorCode::OK)
1965 const uint8_t PRIOR_FAIL = (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1967 :
LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1969 if (!complete_pending_by_rdbuff())
1974 response_value = PRIOR_FAIL;
1978 if (!emit_read_with_ts(pending.need_ts, posted_prev))
1980 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1984 pending.valid =
true;
1985 pending.need_ts = TS;
1986 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1999 const uint8_t PRIOR_FAIL = response_value;
2001 if (!complete_pending_by_rdbuff())
2006 if (PRIOR_FAIL != 0u && PRIOR_FAIL != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2008 response_value = PRIOR_FAIL;
2013 if (response_value == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK && check_write)
2015 uint32_t dummy = 0u;
2016 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2017 const ErrorCode EC = swd_.DpReadRdbuffTxn(dummy, ack);
2018 const uint8_t V = ack_to_dap(ack);
2020 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2026 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2030 resp[1] = response_count;
2031 resp[2] = response_value;
2036template <
typename SwdPort>
2037ErrorCode DapLinkV1Class<SwdPort>::HandleTransferBlock(
bool ,
2039 uint16_t req_len, uint8_t* resp,
2043 if constexpr (JTAG_ENABLED)
2045 if (dap_state_.
debug_port == LibXR::USB::DapLinkV1Def::DebugPort::JTAG)
2047 return HandleJtagTransferBlock(
false, req, req_len, resp, resp_cap, out_len);
2051 if (!resp || resp_cap < 4u)
2057 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK);
2063 if (!req || req_len < 5u)
2065 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2072 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2076 uint16_t count = 0u;
2079 const uint8_t DAP_RQ = req[4];
2081 if ((DAP_RQ & (LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE |
2082 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
2084 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2089 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2095 const uint16_t DONE0 = 0u;
2097 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2109 uint16_t req_off = 5u;
2110 uint16_t resp_off = 4u;
2114 for (uint32_t i = 0; i < count; ++i)
2116 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2119 if (req_off + 4u > req_len)
2121 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2125 uint32_t wdata = 0u;
2127 req_off =
static_cast<uint16_t
>(req_off + 4u);
2131 EC = swd_.ApWriteTxn(ADDR2B, wdata, ack);
2135 EC = swd_.DpWriteTxn(
static_cast<LibXR::Debug::SwdProtocol::DpWriteReg
>(ADDR2B),
2139 xresp = MapAckToDapResp(ack);
2142 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2146 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2153 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2157 done =
static_cast<uint16_t
>(i + 1u);
2168 for (uint32_t i = 0; i < count; ++i)
2170 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2172 uint32_t rdata = 0u;
2174 if (resp_off + 4u > resp_cap)
2176 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2180 EC = swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
2183 xresp = MapAckToDapResp(ack);
2186 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2190 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2197 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2202 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2203 done =
static_cast<uint16_t
>(i + 1u);
2213 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2216 uint32_t dummy_posted = 0u;
2217 EC = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
2218 xresp = MapAckToDapResp(ack);
2222 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2225 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2231 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2235 for (uint32_t i = 1; i < count; ++i)
2237 if (resp_off + 4u > resp_cap)
2239 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2243 uint32_t posted_prev = 0u;
2244 EC = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
2245 const uint8_t CUR = MapAckToDapResp(ack);
2249 xresp = CUR | LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2253 if (ack != LibXR::Debug::SwdProtocol::Ack::OK || EC !=
ErrorCode::OK)
2255 if (resp_off + 4u <= resp_cap)
2258 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2259 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2260 const uint8_t V2 = MapAckToDapResp(ack2);
2265 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2266 done =
static_cast<uint16_t
>(i);
2273 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2282 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2288 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2289 done =
static_cast<uint16_t
>(i);
2293 if (resp_off + 4u > resp_cap)
2295 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2301 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2302 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2303 const uint8_t V2 = MapAckToDapResp(ack2);
2312 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2317 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2329template <
typename SwdPort>
2330ErrorCode DapLinkV1Class<SwdPort>::HandleJtagTransfer(
bool ,
const uint8_t* req,
2331 uint16_t req_len, uint8_t* resp,
2336 if (!req || !resp || resp_cap < 3u)
2341 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER);
2344 uint16_t resp_off = 3u;
2346 if (req_len < 3u || jtag_ ==
nullptr || jtag_chain_.
count == 0u)
2348 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2356 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2361 const uint8_t TAP_INDEX = req[1];
2362 if (TAP_INDEX >= jtag_chain_.
count)
2364 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2369 jtag_chain_.
index = TAP_INDEX;
2370 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
2374 const uint8_t COUNT = req[2];
2375 uint16_t req_off = 3u;
2377 auto push_u32 = [&](uint32_t VALUE) ->
bool
2379 if (resp_off + 4u > resp_cap)
2384 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2388 auto push_timestamp = [&]() ->
bool
2394 auto ensure_space = [&](uint16_t bytes) ->
bool
2395 {
return (resp_off + bytes) <= resp_cap; };
2397 auto bytes_for_read = [&](
bool need_ts) -> uint16_t
2398 {
return static_cast<uint16_t
>(need_ts ? 8u : 4u); };
2400 auto idle_after_attempt = [&]()
2408 auto dp_read_retry = [&](uint8_t addr2b, uint32_t& val,
2409 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2414 const ErrorCode EC = dp.DpReadTxn(addr2b, val, ack);
2415 idle_after_attempt();
2416 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2425 auto dp_write_retry = [&](uint8_t addr2b, uint32_t val,
2426 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2431 const ErrorCode EC = dp.DpWriteTxn(addr2b, val, ack);
2432 idle_after_attempt();
2433 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2442 auto ap_read_retry = [&](uint8_t addr2b, uint32_t& val,
2443 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2448 const ErrorCode EC = dp.ApReadTxn(addr2b, val, ack);
2449 idle_after_attempt();
2450 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2459 auto ap_write_retry = [&](uint8_t addr2b, uint32_t val,
2460 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2465 const ErrorCode EC = dp.ApWriteTxn(addr2b, val, ack);
2466 idle_after_attempt();
2467 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2476 auto check_posted_ap_write_jtag = [&](LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2478 uint32_t ctrl_stat = 0u;
2479 return dp_read_retry(
2480 static_cast<uint8_t
>(LibXR::Debug::SwdProtocol::DpReadReg::CTRL_STAT), ctrl_stat,
2484 uint8_t response_count = 0u;
2485 uint8_t response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2486 bool pending_ap_write =
false;
2488 auto check_posted_ap_write_if_pending = [&]() ->
bool
2490 if (!pending_ap_write)
2495 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2496 const ErrorCode EC = check_posted_ap_write_jtag(ack);
2497 const uint8_t V = MapAckToDapResp(ack);
2499 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2506 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2510 pending_ap_write =
false;
2514 auto should_check_pending_ap_write_at_tail = [&]() ->
bool
2516 return response_value == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK ||
2518 static_cast<uint8_t
>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
2519 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
2522 auto emit_read_with_ts = [&](
bool need_ts, uint32_t data) ->
bool
2526 if (!push_timestamp())
2531 if (!push_u32(data))
2539 for (uint32_t i = 0; i < COUNT; ++i)
2541 if (req_off >= req_len)
2543 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2547 const uint8_t RQ = req[req_off++];
2553 const bool MATCH_VALUE =
2554 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
2555 const bool MATCH_MASK =
2556 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK) != 0u);
2558 if (TS && (MATCH_VALUE || MATCH_MASK))
2560 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2564 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2569 if (req_off + 4u > req_len)
2571 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2575 uint32_t wdata = 0u;
2577 req_off =
static_cast<uint16_t
>(req_off + 4u);
2581 match_mask_ = wdata;
2582 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2589 EC = ap_write_retry(ADDR2B, wdata, ack);
2593 EC = dp_write_retry(ADDR2B, wdata, ack);
2596 response_value = MapAckToDapResp(ack);
2597 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2603 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2609 if (!push_timestamp())
2611 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2619 pending_ap_write =
true;
2626 if (!check_posted_ap_write_if_pending())
2631 if (req_off + 4u > req_len)
2633 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2637 uint32_t match_val = 0u;
2639 req_off =
static_cast<uint16_t
>(req_off + 4u);
2641 uint32_t rdata = 0u;
2643 bool matched =
false;
2649 EC = ap_read_retry(ADDR2B, rdata, ack);
2653 EC = dp_read_retry(ADDR2B, rdata, ack);
2656 response_value = MapAckToDapResp(ack);
2657 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2663 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2667 if ((rdata & match_mask_) == (match_val & match_mask_))
2680 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2688 static_cast<uint8_t
>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
2689 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
2693 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2698 uint32_t rdata = 0u;
2699 if (!check_posted_ap_write_if_pending())
2706 EC = ap_read_retry(ADDR2B, rdata, ack);
2710 EC = dp_read_retry(ADDR2B, rdata, ack);
2713 response_value = MapAckToDapResp(ack);
2714 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2720 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2724 if (!ensure_space(bytes_for_read(TS)))
2726 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2730 if (!emit_read_with_ts(TS, rdata))
2732 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2736 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2746 if (pending_ap_write && should_check_pending_ap_write_at_tail())
2748 const uint8_t PRIOR_RESPONSE = response_value;
2749 if (check_posted_ap_write_if_pending())
2751 response_value = PRIOR_RESPONSE;
2755 resp[1] = response_count;
2756 resp[2] = response_value;
2761template <
typename SwdPort>
2762ErrorCode DapLinkV1Class<SwdPort>::HandleJtagTransferBlock(
2763 bool ,
const uint8_t* req, uint16_t req_len, uint8_t* resp,
2764 uint16_t resp_cap, uint16_t& out_len)
2766 if (!resp || resp_cap < 4u)
2772 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK);
2778 if (!req || req_len < 5u || jtag_ ==
nullptr || jtag_chain_.
count == 0u)
2780 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2787 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2791 const uint8_t TAP_INDEX = req[1];
2792 if (TAP_INDEX >= jtag_chain_.
count)
2794 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2798 jtag_chain_.
index = TAP_INDEX;
2799 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
2801 uint16_t count = 0u;
2804 const uint8_t DAP_RQ = req[4];
2806 if ((DAP_RQ & (LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE |
2807 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
2809 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2814 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2820 const uint16_t DONE0 = 0u;
2822 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2829 auto idle_after_attempt = [&]()
2837 auto dp_read_retry = [&](uint8_t addr2b, uint32_t& val,
2838 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2843 const ErrorCode EC = dp.DpReadTxn(addr2b, val, ack);
2844 idle_after_attempt();
2845 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2854 auto dp_write_retry = [&](uint8_t addr2b, uint32_t val,
2855 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2860 const ErrorCode EC = dp.DpWriteTxn(addr2b, val, ack);
2861 idle_after_attempt();
2862 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2871 auto ap_read_retry = [&](uint8_t addr2b, uint32_t& val,
2872 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2877 const ErrorCode EC = dp.ApReadTxn(addr2b, val, ack);
2878 idle_after_attempt();
2879 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2888 auto ap_write_retry = [&](uint8_t addr2b, uint32_t val,
2889 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2894 const ErrorCode EC = dp.ApWriteTxn(addr2b, val, ack);
2895 idle_after_attempt();
2896 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
2905 auto check_posted_ap_write_jtag = [&](LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
2907 uint32_t ctrl_stat = 0u;
2908 return dp_read_retry(
2909 static_cast<uint8_t
>(LibXR::Debug::SwdProtocol::DpReadReg::CTRL_STAT), ctrl_stat,
2920 uint16_t req_off = 5u;
2921 uint16_t resp_off = 4u;
2925 for (uint32_t i = 0; i < count; ++i)
2927 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2930 if (req_off + 4u > req_len)
2932 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2936 uint32_t wdata = 0u;
2938 req_off =
static_cast<uint16_t
>(req_off + 4u);
2942 EC = ap_write_retry(ADDR2B, wdata, ack);
2946 EC = dp_write_retry(ADDR2B, wdata, ack);
2949 xresp = MapAckToDapResp(ack);
2952 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2956 if (ack != LibXR::Debug::JtagProtocol::Ack::OK)
2963 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2967 done =
static_cast<uint16_t
>(i + 1u);
2970 if (AP && xresp == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK && done > 0u)
2972 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2973 const ErrorCode EC = check_posted_ap_write_jtag(ack);
2974 const uint8_t V = MapAckToDapResp(ack);
2975 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2981 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2991 for (uint32_t i = 0; i < count; ++i)
2993 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
2995 uint32_t rdata = 0u;
2997 if (resp_off + 4u > resp_cap)
2999 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
3005 EC = ap_read_retry(ADDR2B, rdata, ack);
3009 EC = dp_read_retry(ADDR2B, rdata, ack);
3012 xresp = MapAckToDapResp(ack);
3015 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
3019 if (ack != LibXR::Debug::JtagProtocol::Ack::OK)
3026 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
3031 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
3032 done =
static_cast<uint16_t
>(i + 1u);
3041template <
typename SwdPort>
3042ErrorCode DapLinkV1Class<SwdPort>::HandleJtagWriteAbort(
bool ,
3044 uint16_t req_len, uint8_t* resp,
3048 if (!resp || resp_cap < 2u)
3054 resp[0] = to_u8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT);
3055 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::ERROR);
3058 if (!req || req_len < 6u || jtag_ ==
nullptr || jtag_chain_.
count == 0u)
3063 const uint8_t TAP_INDEX = req[1];
3064 if (TAP_INDEX >= jtag_chain_.
count)
3069 jtag_chain_.
index = TAP_INDEX;
3070 LibXR::Debug::JtagProtocol::UpdateChainCache(jtag_chain_);
3072 uint32_t flags = 0u;
3076 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
3077 const ErrorCode EC = dp.WriteAbort(flags, ack);
3078 const uint8_t V = MapAckToDapResp(ack);
3080 if (EC ==
ErrorCode::OK && V == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
3082 resp[1] = to_u8(LibXR::USB::DapLinkV1Def::Status::OK);
3088template <
typename SwdPort>
3089void DapLinkV1Class<SwdPort>::DriveReset(
bool release)
3091 last_nreset_level_high_ = release;
3095 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
3099 swj_shadow_ =
static_cast<uint8_t
>(
3100 swj_shadow_ &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
3103 if (nreset_gpio_ !=
nullptr)
3105 (void)nreset_gpio_->
Write(release);
3109template <
typename SwdPort>
3110void 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
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
JTAG-DP 事务层封装(DP/AP 访问与 IDCODE/ABORT)。
Abstract JTAG base class providing TAP control and IR/DR shifting.
virtual void Close()=0
Close JTAG and release resources.
virtual ErrorCode Sequence(uint32_t cycles, bool tms, const uint8_t *tdi_lsb_first, uint8_t *tdo_lsb_first)=0
Shift a fixed-TMS sequence, LSB first.
virtual ErrorCode SetClockHz(uint32_t hz)=0
Set TCK frequency, if supported.
virtual void IdleClocks(uint32_t cycles)=0
Insert idle clock cycles in Run-Test/Idle.
通用输入输出(GPIO)接口类。General Purpose Input/Output (GPIO) interface class.
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
ConstRawData GetReportDesc() override
获取 HID 报告描述符 Get HID Report Descriptor
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
USB描述符基类 USB descriptor base class.
Data data_
设备描述符数据实例 / Internal data instance
@ HID
人机接口类 / Human Interface Device
EPNumber
端点号 Endpoint number
@ 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
size_t GetActiveLength()
获取当前活动缓冲区有效长度 / Get active buffer valid length
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 DAP_CAP_SWD
支持 SWD。Supports SWD.
static constexpr std::uint8_t DAP_CAP_JTAG
支持 JTAG。Supports JTAG.
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
JTAG 设备链配置 / JTAG device chain configuration.
uint8_t count
设备数(TDO 端为 index=0)/ Device count (TDO side index=0)
uint32_t ir_before_bits_len
前面设备 IR 总位数 / IR bits before
uint32_t ir_after_bits_len
后面设备 IR 总位数 / IR bits after
uint32_t dr_after_bits_len
后面设备 DR 总位数 / DR bits after
uint8_t index
当前设备索引 / Current device index
uint32_t dr_before_bits_len
前面设备 DR 总位数 / DR bits before
传输策略(WAIT 重试与空闲周期插入)。Transfer policy (WAIT retry & idle insertion).
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.
ClassID bDeviceClass
设备类代码 / Device class code
uint8_t bDeviceSubClass
设备子类代码 / Device subclass code
uint8_t bDeviceProtocol
协议代码 / Protocol code