41 static constexpr bool JTAG_ENABLED = DapLinkV2BuildConfig::kEnableJtag;
42 static constexpr const char* DEFAULT_INTERFACE_STRING =
"CMSIS-DAP v2";
74 const char* interface_string = DEFAULT_INTERFACE_STRING)
85 InitWinUsbDescriptors();
110 if constexpr (JTAG_ENABLED)
114 ResetJtagChainState();
115 if (
jtag_ !=
nullptr)
176 UpdateWinUsbInterfaceFields();
199 desc_block_.
intf = {9,
200 static_cast<uint8_t
>(DescriptorType::INTERFACE),
210 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
216 desc_block_.
ep_in = {7,
217 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
223 SetData(
RawData{
reinterpret_cast<uint8_t*
>(&desc_block_),
sizeof(desc_block_)});
232 if constexpr (JTAG_ENABLED)
234 if (
jtag_ !=
nullptr)
242 swj_shadow_ =
static_cast<uint8_t
>(DapLinkV2Def::DAP_SWJ_SWDIO_TMS |
243 DapLinkV2Def::DAP_SWJ_NRESET);
245 ResetResponseQueue();
246 ResetQueuedCommandState();
247 ResetJtagChainState();
251 ArmOutTransferIfIdle();
262 ResetResponseQueue();
263 ResetQueuedCommandState();
285 if constexpr (JTAG_ENABLED)
287 if (
jtag_ !=
nullptr)
295 swj_shadow_ =
static_cast<uint8_t
>(DapLinkV2Def::DAP_SWJ_SWDIO_TMS |
296 DapLinkV2Def::DAP_SWJ_NRESET);
338 return ConstRawData{
reinterpret_cast<const uint8_t*
>(&winusb_msos20_),
339 sizeof(winusb_msos20_)};
368 template <
typename E>
369 static constexpr uint8_t ToU8(E e)
371 return static_cast<uint8_t
>(e);
379 static inline ErrorCode BuildUnknownCmdResponse(uint8_t* resp, uint16_t cap,
382 if (!resp || cap < 1u)
393 static inline ErrorCode BuildCmdStatusResponse(uint8_t cmd, uint8_t status,
394 uint8_t* resp, uint16_t cap,
397 if (!resp || cap < 2u)
413 void InitWinUsbDescriptors()
415 winusb_msos20_.
set.wLength =
static_cast<uint16_t
>(
sizeof(winusb_msos20_.
set));
416 winusb_msos20_.
set.wDescriptorType =
417 LibXR::USB::WinUsbMsOs20::MS_OS_20_SET_HEADER_DESCRIPTOR;
418 winusb_msos20_.
set.dwWindowsVersion = 0x06030000;
419 winusb_msos20_.
set.wTotalLength =
static_cast<uint16_t
>(
sizeof(winusb_msos20_));
421 winusb_msos20_.
cfg.wLength =
static_cast<uint16_t
>(
sizeof(winusb_msos20_.
cfg));
422 winusb_msos20_.
cfg.wDescriptorType =
423 LibXR::USB::WinUsbMsOs20::MS_OS_20_SUBSET_HEADER_CONFIGURATION;
426 winusb_msos20_.
cfg.bConfigurationValue = 0u;
427 winusb_msos20_.
cfg.bReserved = 0;
428 winusb_msos20_.
cfg.wTotalLength =
static_cast<uint16_t
>(
429 sizeof(winusb_msos20_) - offsetof(WinUsbMsOs20DescSet, cfg));
431 winusb_msos20_.
func.wLength =
static_cast<uint16_t
>(
sizeof(winusb_msos20_.
func));
432 winusb_msos20_.
func.wDescriptorType =
433 LibXR::USB::WinUsbMsOs20::MS_OS_20_SUBSET_HEADER_FUNCTION;
434 winusb_msos20_.
func.bReserved = 0;
435 winusb_msos20_.
func.wTotalLength =
static_cast<uint16_t
>(
436 sizeof(winusb_msos20_) - offsetof(WinUsbMsOs20DescSet, func));
438 winusb_msos20_.
compat.wLength =
static_cast<uint16_t
>(
sizeof(winusb_msos20_.
compat));
439 winusb_msos20_.
compat.wDescriptorType =
440 LibXR::USB::WinUsbMsOs20::MS_OS_20_FEATURE_COMPATIBLE_ID;
442 winusb_msos20_.prop.
header.wDescriptorType =
443 LibXR::USB::WinUsbMsOs20::MS_OS_20_FEATURE_REG_PROPERTY;
444 winusb_msos20_.prop.
header.wPropertyDataType = LibXR::USB::WinUsbMsOs20::REG_MULTI_SZ;
445 winusb_msos20_.prop.
header.wPropertyNameLength =
446 LibXR::USB::WinUsbMsOs20::PROP_NAME_DEVICE_INTERFACE_GUIDS_BYTES;
449 LibXR::USB::WinUsbMsOs20::PROP_NAME_DEVICE_INTERFACE_GUIDS_UTF16,
450 LibXR::USB::WinUsbMsOs20::PROP_NAME_DEVICE_INTERFACE_GUIDS_BYTES);
454 const char GUID_STR[] =
"{CDB3B5AD-293B-4663-AA36-1AAE46463776}";
455 const size_t GUID_LEN =
sizeof(GUID_STR) - 1;
457 for (
size_t i = 0; i < GUID_LEN; ++i)
459 winusb_msos20_.prop.
data[i * 2] =
static_cast<uint8_t
>(GUID_STR[i]);
460 winusb_msos20_.prop.
data[i * 2 + 1] = 0x00;
464 winusb_msos20_.prop.
data[GUID_LEN * 2 + 0] = 0x00;
465 winusb_msos20_.prop.
data[GUID_LEN * 2 + 1] = 0x00;
466 winusb_msos20_.prop.
data[GUID_LEN * 2 + 2] = 0x00;
467 winusb_msos20_.prop.
data[GUID_LEN * 2 + 3] = 0x00;
470 winusb_msos20_.prop.
header.wLength =
471 static_cast<uint16_t
>(
sizeof(winusb_msos20_.prop));
478 void UpdateWinUsbInterfaceFields()
528 const auto* req =
static_cast<const uint8_t*
>(data.
addr_);
529 const uint16_t REQ_LEN =
static_cast<uint16_t
>(data.
size_);
533 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
535 CanBuildResponseDirectlyInEpBuffer())
538 if (tx_buff.addr_ && tx_buff.size_ > 0u)
540 auto* tx_buf =
static_cast<uint8_t*
>(tx_buff.addr_);
541 uint16_t out_len = 0u;
543 static_cast<uint16_t
>(tx_buff.size_), out_len);
547 if (StartInTransferFromCurrentBuffer(out_len))
552 if (!EnqueueResponse(tx_buf, out_len))
554 (void)SubmitNextQueuedResponseIfIdle();
555 (void)EnqueueResponse(tx_buf, out_len);
558 (void)SubmitNextQueuedResponseIfIdle();
559 ArmOutTransferIfIdle();
566 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
568 CanBuildResponseDirectlyInEpBuffer())
571 if (tx_buff.addr_ && tx_buff.size_ > 0u)
573 auto* tx_buf =
static_cast<uint8_t*
>(tx_buff.addr_);
574 uint16_t out_len = 0u;
576 static_cast<uint16_t
>(tx_buff.size_), out_len);
580 SetDeferredResponseInEpBuffer(out_len);
581 ArmOutTransferIfIdle();
586 if (TryBuildAndEnqueueResponse(in_isr, req, REQ_LEN))
588 (void)SubmitDeferredResponseIfIdle();
589 (void)SubmitNextQueuedResponseIfIdle();
590 ArmOutTransferIfIdle();
595 (void)SubmitNextQueuedResponseIfIdle();
596 (void)TryBuildAndEnqueueResponse(in_isr, req, REQ_LEN);
598 (void)SubmitDeferredResponseIfIdle();
599 (void)SubmitNextQueuedResponseIfIdle();
600 ArmOutTransferIfIdle();
608 (void)SubmitDeferredResponseIfIdle();
609 (void)SubmitNextQueuedResponseIfIdle();
610 ArmOutTransferIfIdle();
619 constexpr uint16_t OPENOCD_SAFE_PS =
static_cast<uint16_t
>((255u * 5u) + 4u);
620 constexpr uint16_t RAW_PS =
621 (MaxDapPacketSize == 0u) ? DefaultDapPacketSize : MaxDapPacketSize;
622 return (RAW_PS > OPENOCD_SAFE_PS) ? OPENOCD_SAFE_PS : RAW_PS;
624 bool CanBuildResponseDirectlyInEpBuffer()
const
631 if (!tx_buff.addr_ || tx_buff.size_ == 0u)
638 bool StartInTransferFromCurrentBuffer(uint16_t len)
645 if (!tx_buff.addr_ || tx_buff.size_ == 0u)
649 uint16_t tx_len = len;
650 if (tx_len > tx_buff.size_)
652 tx_len =
static_cast<uint16_t
>(tx_buff.size_);
661 bool StartInTransferFromPayload(
const uint8_t* data, uint16_t len)
668 if (!tx_buff.addr_ || tx_buff.size_ == 0u)
672 uint16_t tx_len = len;
673 if (tx_len > MAX_DAP_PACKET_SIZE)
675 tx_len = MAX_DAP_PACKET_SIZE;
678 if (tx_len <= MAX_XFER && tx_len <=
static_cast<uint16_t
>(tx_buff.size_))
686 if (tx_len >
static_cast<uint16_t
>(
sizeof(in_tx_multi_storage_)))
688 tx_len =
static_cast<uint16_t
>(
sizeof(in_tx_multi_storage_));
690 if (tx_len > 0u && data != in_tx_multi_storage_)
694 in_tx_multi_buf_.
addr_ = in_tx_multi_storage_;
695 in_tx_multi_buf_.
size_ = tx_len;
709 if (len > RESP_SLOT_SIZE)
711 len = RESP_SLOT_SIZE;
720 static constexpr uint8_t NextRespQueueIndex(uint8_t idx)
722 return static_cast<uint8_t
>((idx + 1u) & (RESP_QUEUE_DEPTH - 1u));
725 void ResetResponseQueue()
730 deferred_in_resp_valid_ =
false;
731 deferred_in_resp_len_ = 0u;
734 bool HasDeferredResponseInEpBuffer()
const {
return deferred_in_resp_valid_; }
736 void SetDeferredResponseInEpBuffer(uint16_t len)
738 deferred_in_resp_len_ = len;
739 deferred_in_resp_valid_ =
true;
742 bool SubmitDeferredResponseIfIdle()
750 const uint16_t TX_LEN = deferred_in_resp_len_;
751 if (!StartInTransferFromCurrentBuffer(TX_LEN))
756 deferred_in_resp_valid_ =
false;
757 deferred_in_resp_len_ = 0u;
761 bool IsResponseQueueEmpty()
const {
return resp_q_count_ == 0u; }
763 bool IsResponseQueueFull()
const {
return resp_q_count_ >= RESP_QUEUE_DEPTH; }
765 void ResetQueuedCommandState()
767 queued_request_length_ = 0u;
768 queued_command_count_ = 0u;
784 uint16_t& cmd_len)
const
787 if (!req || avail < 1u)
792 const uint8_t CMD = req[0];
795 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::INFO):
797 return avail >= cmd_len;
798 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::HOST_STATUS):
800 return avail >= cmd_len;
801 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::CONNECT):
803 return avail >= cmd_len;
804 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::DISCONNECT):
806 return avail >= cmd_len;
807 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_CONFIGURE):
809 return avail >= cmd_len;
810 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_ABORT):
812 return avail >= cmd_len;
813 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::WRITE_ABORT):
815 return avail >= cmd_len;
816 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::DELAY):
818 return avail >= cmd_len;
819 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::RESET_TARGET):
821 return avail >= cmd_len;
822 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_PINS):
824 return avail >= cmd_len;
825 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_CLOCK):
827 return avail >= cmd_len;
828 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_CONFIGURE):
830 return avail >= cmd_len;
831 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_SEQUENCE):
837 const uint32_t BIT_COUNT = (req[1] == 0u) ? 256u :
static_cast<uint32_t
>(req[1]);
838 const uint32_t BYTE_COUNT = (BIT_COUNT + 7u) / 8u;
839 const uint32_t NEED = 2u + BYTE_COUNT;
844 cmd_len =
static_cast<uint16_t
>(NEED);
847 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_SEQUENCE):
853 const uint8_t SEQ_CNT = req[1];
855 for (uint32_t i = 0u; i < SEQ_CNT; ++i)
862 const uint8_t INFO = req[off++];
863 uint32_t cycles =
static_cast<uint32_t
>(INFO & 0x3Fu);
869 const bool MODE_IN = ((INFO & 0x80u) != 0u);
870 const uint32_t BYTES = (cycles + 7u) / 8u;
873 if (off + BYTES > avail)
880 cmd_len =
static_cast<uint16_t
>(off);
883 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER):
889 const uint8_t COUNT = req[2];
891 for (uint32_t i = 0u; i < COUNT; ++i)
898 const uint8_t RQ = req[off++];
900 const bool MATCH_VALUE =
901 ((RQ & LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
902 if (!RNW || MATCH_VALUE)
904 if (off + 4u > avail)
911 cmd_len =
static_cast<uint16_t
>(off);
914 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_BLOCK):
926 need +=
static_cast<uint32_t
>(count) * 4u;
932 cmd_len =
static_cast<uint16_t
>(need);
937 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS):
938 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::EXECUTE_COMMANDS):
957 if (!resp || resp_cap < 1u)
962 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::EXECUTE_COMMANDS);
965 if (queued_command_count_ == 0u)
970 uint16_t req_off = 0u;
971 uint16_t resp_off = 1u;
972 for (uint32_t i = 0u; i < queued_command_count_; ++i)
974 if (req_off >= queued_request_length_)
979 uint16_t cmd_len = 0u;
981 &queued_request_buffer_[req_off],
982 static_cast<uint16_t
>(queued_request_length_ - req_off), cmd_len) ||
988 if (resp_off >= resp_cap)
993 uint16_t cmd_out = 0u;
995 in_isr, &queued_request_buffer_[req_off], cmd_len, &resp[resp_off],
996 static_cast<uint16_t
>(resp_cap - resp_off), cmd_out);
999 if (
static_cast<uint32_t
>(resp_off) +
static_cast<uint32_t
>(cmd_out) >
1000 static_cast<uint32_t
>(resp_cap))
1005 req_off =
static_cast<uint16_t
>(req_off + cmd_len);
1006 resp_off =
static_cast<uint16_t
>(resp_off + cmd_out);
1009 if (req_off != queued_request_length_)
1018 bool TryBuildAndEnqueueResponse(
bool in_isr,
const uint8_t* req, uint16_t req_len)
1020 if (!req || IsResponseQueueFull())
1025 auto& slot = resp_q_[resp_q_tail_];
1026 uint16_t out_len = 0u;
1032 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
1037 uint8_t OutstandingResponseCount()
const
1039 const uint8_t IN_FLIGHT =
1041 const uint8_t DEFERRED = deferred_in_resp_valid_ ? 1u : 0u;
1042 return static_cast<uint8_t
>(resp_q_count_ + IN_FLIGHT + DEFERRED);
1045 bool EnqueueResponse(
const uint8_t* data, uint16_t len)
1047 if (!data || IsResponseQueueFull())
1052 auto& slot = resp_q_[resp_q_tail_];
1060 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
1065 bool SubmitNextQueuedResponseIfIdle()
1068 IsResponseQueueEmpty())
1072 auto& slot = resp_q_[resp_q_head_];
1073 if (!StartInTransferFromPayload(slot.payload, slot.len))
1077 resp_q_head_ = NextRespQueueIndex(resp_q_head_);
1082 void ArmOutTransferIfIdle()
1095 if (OutstandingResponseCount() >= MAX_OUTSTANDING_RESPONSES)
1101 if (out_rx_len == 0u)
1103 out_rx_len = DEFAULT_DAP_PACKET_SIZE;
1105 if (out_rx_len > MAX_DAP_PACKET_SIZE)
1107 out_rx_len = MAX_DAP_PACKET_SIZE;
1111 if (OUT_MAX_XFER == 0u)
1116 if (out_rx_len <= OUT_MAX_XFER)
1122 if (out_rx_len >
static_cast<uint16_t
>(
sizeof(out_req_multi_storage_)))
1124 out_rx_len =
static_cast<uint16_t
>(
sizeof(out_req_multi_storage_));
1129 out_req_multi_buf_.
addr_ = out_req_multi_storage_;
1130 out_req_multi_buf_.
size_ = out_rx_len;
1151 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1155 if (!req || !resp || req_len < 1u || resp_cap < 1u)
1157 if (resp && resp_cap >= 1u)
1164 const uint8_t CMD = req[0];
1168 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::INFO):
1169 return HandleInfo(in_isr, req, req_len, resp, resp_cap, out_len);
1170 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::HOST_STATUS):
1171 return HandleHostStatus(in_isr, req, req_len, resp, resp_cap, out_len);
1172 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::CONNECT):
1173 return HandleConnect(in_isr, req, req_len, resp, resp_cap, out_len);
1174 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::DISCONNECT):
1175 return HandleDisconnect(in_isr, req, req_len, resp, resp_cap, out_len);
1176 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_CONFIGURE):
1177 return HandleTransferConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
1178 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER):
1179 return HandleTransfer(in_isr, req, req_len, resp, resp_cap, out_len);
1180 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_BLOCK):
1181 return HandleTransferBlock(in_isr, req, req_len, resp, resp_cap, out_len);
1182 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_ABORT):
1183 return HandleTransferAbort(in_isr, req, req_len, resp, resp_cap, out_len);
1184 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::WRITE_ABORT):
1185 return HandleWriteABORT(in_isr, req, req_len, resp, resp_cap, out_len);
1186 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::DELAY):
1187 return HandleDelay(in_isr, req, req_len, resp, resp_cap, out_len);
1188 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::RESET_TARGET):
1189 return HandleResetTarget(in_isr, req, req_len, resp, resp_cap, out_len);
1191 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_PINS):
1192 return HandleSWJPins(in_isr, req, req_len, resp, resp_cap, out_len);
1193 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_CLOCK):
1194 return HandleSWJClock(in_isr, req, req_len, resp, resp_cap, out_len);
1195 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_SEQUENCE):
1196 return HandleSWJSequence(in_isr, req, req_len, resp, resp_cap, out_len);
1197 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_CONFIGURE):
1198 return HandleSWDConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
1199 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_SEQUENCE):
1200 return HandleSWDSequence(in_isr, req, req_len, resp, resp_cap, out_len);
1202 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::JTAG_SEQUENCE):
1203 if constexpr (JTAG_ENABLED)
1205 return HandleJTAGSequence(in_isr, req, req_len, resp, resp_cap, out_len);
1207 (void)BuildUnknownCmdResponse(resp, resp_cap, out_len);
1209 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::JTAG_CONFIGURE):
1210 if constexpr (JTAG_ENABLED)
1212 return HandleJTAGConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
1214 (void)BuildUnknownCmdResponse(resp, resp_cap, out_len);
1216 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::JTAG_IDCODE):
1217 if constexpr (JTAG_ENABLED)
1219 return HandleJTAGIdCode(in_isr, req, req_len, resp, resp_cap, out_len);
1221 (void)BuildUnknownCmdResponse(resp, resp_cap, out_len);
1224 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS):
1226 case ToU8(LibXR::USB::DapLinkV2Def::CommandId::EXECUTE_COMMANDS):
1230 (void)BuildUnknownCmdResponse(resp, resp_cap, out_len);
1244 if (!resp || resp_cap < 1u)
1258 ErrorCode HandleInfo(
bool ,
const uint8_t* req, uint16_t req_len,
1259 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1263 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::INFO);
1269 const uint8_t INFO_ID = req[1];
1271 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::INFO);
1275 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::VENDOR):
1276 return BuildInfoStringResponse(resp[0],
info_.vendor, resp, resp_cap, out_len);
1277 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PRODUCT):
1278 return BuildInfoStringResponse(resp[0],
info_.product, resp, resp_cap, out_len);
1279 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::SERIAL_NUMBER):
1280 return BuildInfoStringResponse(resp[0],
info_.serial, resp, resp_cap, out_len);
1281 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::FIRMWARE_VERSION):
1282 return BuildInfoStringResponse(resp[0],
info_.firmware_ver, resp, resp_cap,
1285 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::DEVICE_VENDOR):
1286 return BuildInfoStringResponse(resp[0],
info_.device_vendor, resp, resp_cap,
1288 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::DEVICE_NAME):
1289 return BuildInfoStringResponse(resp[0],
info_.device_name, resp, resp_cap,
1291 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::BOARD_VENDOR):
1292 return BuildInfoStringResponse(resp[0],
info_.board_vendor, resp, resp_cap,
1294 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::BOARD_NAME):
1295 return BuildInfoStringResponse(resp[0],
info_.board_name, resp, resp_cap,
1297 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PRODUCT_FIRMWARE_VERSION):
1298 return BuildInfoStringResponse(resp[0],
info_.product_fw_ver, resp, resp_cap,
1301 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::CAPABILITIES):
1304 if constexpr (JTAG_ENABLED)
1306 if (
jtag_ !=
nullptr)
1311 return BuildInfoU8Response(resp[0], caps, resp, resp_cap, out_len);
1313 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PACKET_COUNT):
1314 return BuildInfoU8Response(resp[0], PACKET_COUNT_EFFECTIVE, resp, resp_cap,
1316 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::PACKET_SIZE):
1319 return BuildInfoU16Response(resp[0], DAP_PS, resp, resp_cap, out_len);
1321 case ToU8(LibXR::USB::DapLinkV2Def::InfoId::TIMESTAMP_CLOCK):
1322 return BuildInfoU32Response(resp[0], 1000000U, resp, resp_cap, out_len);
1331 ErrorCode BuildInfoStringResponse(uint8_t cmd,
const char* str, uint8_t* resp,
1332 uint16_t resp_cap, uint16_t& out_len)
1343 const size_t N_WITH_NUL = std::strlen(str) + 1;
1344 const size_t MAX_PAYLOAD = (resp_cap >= 2u) ? (resp_cap - 2u) : 0u;
1345 if (MAX_PAYLOAD == 0u)
1351 const size_t COPY_N = (N_WITH_NUL > MAX_PAYLOAD) ? MAX_PAYLOAD : N_WITH_NUL;
1355 resp[2 + COPY_N - 1] = 0x00;
1357 resp[1] =
static_cast<uint8_t
>(COPY_N);
1358 out_len =
static_cast<uint16_t
>(2u + COPY_N);
1362 ErrorCode BuildInfoU8Response(uint8_t cmd, uint8_t val, uint8_t* resp,
1363 uint16_t resp_cap, uint16_t& out_len)
1377 ErrorCode BuildInfoU16Response(uint8_t cmd, uint16_t val, uint8_t* resp,
1378 uint16_t resp_cap, uint16_t& out_len)
1395 ErrorCode BuildInfoU32Response(uint8_t cmd, uint32_t val, uint8_t* resp,
1396 uint16_t resp_cap, uint16_t& out_len)
1418 ErrorCode HandleHostStatus(
bool ,
const uint8_t* ,
1419 uint16_t , uint8_t* resp, uint16_t resp_cap,
1427 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::HOST_STATUS);
1428 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1433 ErrorCode HandleConnect(
bool ,
const uint8_t* req, uint16_t req_len,
1434 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1442 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::CONNECT);
1450 if (port == 0u || port == ToU8(LibXR::USB::DapLinkV2Def::Port::SWD))
1452 (void)
swd_.EnterSwd();
1457 ResetQueuedCommandState();
1459 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Port::SWD);
1461 else if (port == ToU8(LibXR::USB::DapLinkV2Def::Port::JTAG))
1463 if constexpr (!JTAG_ENABLED)
1465 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Port::DISABLED);
1469 if (
jtag_ ==
nullptr)
1471 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Port::DISABLED);
1475 static constexpr uint8_t SWD_TO_JTAG_SEQUENCE[2] = {0x3Cu, 0xE7u};
1477 (void)
swd_.LineReset();
1478 (void)
swd_.SeqWriteBits(16u, SWD_TO_JTAG_SEQUENCE);
1479 (void)
swd_.LineReset();
1485 ResetQueuedCommandState();
1486 ResetJtagChainState();
1487 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Port::JTAG);
1493 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Port::DISABLED);
1500 ErrorCode HandleDisconnect(
bool ,
const uint8_t* ,
1501 uint16_t , uint8_t* resp, uint16_t resp_cap,
1511 if constexpr (JTAG_ENABLED)
1513 if (
jtag_ !=
nullptr)
1520 ResetQueuedCommandState();
1522 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::DISCONNECT);
1523 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1528 ErrorCode HandleTransferConfigure(
bool ,
const uint8_t* req, uint16_t req_len,
1529 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1537 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_CONFIGURE);
1542 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1547 const uint8_t IDLE = req[1];
1549 uint16_t wait_retry = 0u;
1550 uint16_t match_retry = 0u;
1559 Debug::Swd::TransferPolicy pol =
swd_.GetTransferPolicy();
1560 pol.idle_cycles = IDLE;
1561 pol.wait_retry = wait_retry;
1562 swd_.SetTransferPolicy(pol);
1564 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1569 ErrorCode HandleTransferAbort(
bool ,
const uint8_t* ,
1570 uint16_t , uint8_t* resp, uint16_t resp_cap,
1579 SetTransferAbortFlag(
true);
1581 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_ABORT);
1582 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1587 ErrorCode HandleWriteABORT(
bool in_isr,
const uint8_t* req, uint16_t req_len,
1588 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1596 if constexpr (JTAG_ENABLED)
1600 return HandleJtagWriteAbort(in_isr, req, req_len, resp, resp_cap, out_len);
1604 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::WRITE_ABORT);
1608 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1613 uint32_t flags = 0u;
1616 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1619 resp[1] = (EC ==
ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1620 ? ToU8(LibXR::USB::DapLinkV2Def::Status::OK)
1621 : ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1627 ErrorCode HandleDelay(
bool ,
const uint8_t* req, uint16_t req_len,
1628 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1636 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::DELAY);
1640 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1650 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1655 ErrorCode HandleResetTarget(
bool in_isr,
const uint8_t* , uint16_t ,
1656 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1658 if (!resp || resp_cap < 3u)
1664 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::RESET_TARGET);
1666 uint8_t execute = 0u;
1671 DelayUsIfAllowed(in_isr, 1000u);
1673 DelayUsIfAllowed(in_isr, 1000u);
1688 ErrorCode HandleSWJPins(
bool ,
const uint8_t* req, uint16_t req_len,
1689 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1691 if (!resp || resp_cap < 2u)
1697 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_PINS);
1700 if (!req || req_len < 7u)
1707 const uint8_t PIN_OUT = req[1];
1708 const uint8_t PIN_SEL = req[2];
1710 uint32_t wait_us = 0u;
1715 (PIN_OUT & PIN_SEL));
1718 if ((PIN_SEL & LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET) != 0u)
1720 const bool LEVEL_HIGH =
1721 ((PIN_OUT & LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET) != 0u);
1724 DriveReset(LEVEL_HIGH);
1728 auto read_pins = [&]() -> uint8_t
1736 pin_in |= LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET;
1740 pin_in =
static_cast<uint8_t
>(
1741 pin_in &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET));
1751 uint8_t pin_in = 0u;
1753 if (wait_us == 0u || PIN_SEL == 0u)
1755 pin_in = read_pins();
1760 const uint8_t EXPECT =
static_cast<uint8_t
>(PIN_OUT & PIN_SEL);
1764 pin_in = read_pins();
1765 if ((pin_in & PIN_SEL) == EXPECT)
1778 ErrorCode HandleSWJClock(
bool ,
const uint8_t* req, uint16_t req_len,
1779 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1787 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_CLOCK);
1791 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1800 (void)
swd_.SetClockHz(hz);
1801 if constexpr (JTAG_ENABLED)
1803 if (
jtag_ !=
nullptr)
1809 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1814 ErrorCode HandleSWJSequence(
bool ,
const uint8_t* req, uint16_t req_len,
1815 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1817 if (!resp || resp_cap < 2u)
1823 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWJ_SEQUENCE);
1824 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1828 if (!req || req_len < 2u)
1830 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1834 const uint8_t RAW_COUNT = req[1];
1835 const uint32_t BIT_COUNT =
1836 (RAW_COUNT == 0u) ? 256u : static_cast<uint32_t>(RAW_COUNT);
1837 const uint32_t BYTE_COUNT = (BIT_COUNT + 7u) / 8u;
1839 if (2u + BYTE_COUNT > req_len)
1841 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1845 const uint8_t* data = &req[2];
1851 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1858 swj_shadow_ &
static_cast<uint8_t
>(
~LibXR::USB::DapLinkV2Def::DAP_SWJ_SWCLK_TCK));
1860 bool last_swdio =
false;
1861 if (BIT_COUNT != 0u)
1863 const uint32_t LAST_I = BIT_COUNT - 1u;
1864 last_swdio = (((data[LAST_I / 8u] >> (LAST_I & 7u)) & 0x01u) != 0u);
1869 swj_shadow_ |= LibXR::USB::DapLinkV2Def::DAP_SWJ_SWDIO_TMS;
1875 static_cast<uint8_t
>(
~LibXR::USB::DapLinkV2Def::DAP_SWJ_SWDIO_TMS));
1881 ErrorCode HandleSWDConfigure(
bool ,
const uint8_t* req, uint16_t req_len,
1882 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1890 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_CONFIGURE);
1892 if (req ==
nullptr || req_len < 2u)
1894 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::ERROR);
1899 const uint8_t cfg = req[1];
1903 resp[1] = ToU8(LibXR::USB::DapLinkV2Def::Status::OK);
1908 ErrorCode HandleSWDSequence(
bool ,
const uint8_t* req, uint16_t req_len,
1909 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
1911 if (!req || !resp || resp_cap < 2u)
1917 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::SWD_SEQUENCE);
1934 const uint8_t SEQ_CNT = req[1];
1935 uint16_t req_off = 2u;
1936 uint16_t resp_off = 2u;
1938 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1940 if (req_off >= req_len)
1947 const uint8_t INFO = req[req_off++];
1949 uint32_t cycles =
static_cast<uint32_t
>(INFO & 0x3Fu);
1955 const bool MODE_IN = ((INFO & 0x80u) != 0u);
1956 const uint16_t BYTES =
static_cast<uint16_t
>((cycles + 7u) / 8u);
1961 if (req_off + BYTES > req_len)
1968 const uint8_t* data = &req[req_off];
1969 req_off =
static_cast<uint16_t
>(req_off + BYTES);
1983 if (resp_off + BYTES > resp_cap)
1992 const ErrorCode EC =
swd_.SeqReadBits(cycles, &resp[resp_off]);
2000 resp_off =
static_cast<uint16_t
>(resp_off + BYTES);
2008 ErrorCode HandleJTAGSequence(
bool ,
const uint8_t* req, uint16_t req_len,
2009 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
2011 if (!req || !resp || resp_cap < 2u)
2017 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::JTAG_SEQUENCE);
2021 if (
jtag_ ==
nullptr)
2033 const uint8_t SEQ_CNT = req[1];
2034 uint16_t req_off = 2u;
2035 uint16_t resp_off = 2u;
2037 for (uint32_t s = 0; s < SEQ_CNT; ++s)
2039 if (req_off >= req_len)
2046 const uint8_t INFO = req[req_off++];
2047 uint32_t cycles =
static_cast<uint32_t
>(INFO & 0x3Fu);
2053 const bool TMS = ((INFO & LibXR::Debug::JtagProtocol::JTAG_SEQUENCE_TMS) != 0u);
2054 const bool CAPTURE = ((INFO & LibXR::Debug::JtagProtocol::JTAG_SEQUENCE_TDO) != 0u);
2055 const uint16_t BYTES =
static_cast<uint16_t
>((cycles + 7u) / 8u);
2057 if (req_off + BYTES > req_len)
2063 if (CAPTURE && (resp_off + BYTES > resp_cap))
2070 const uint8_t* data = &req[req_off];
2071 uint8_t* out = CAPTURE ? &resp[resp_off] :
nullptr;
2085 req_off =
static_cast<uint16_t
>(req_off + BYTES);
2088 resp_off =
static_cast<uint16_t
>(resp_off + BYTES);
2096 ErrorCode HandleJTAGConfigure(
bool ,
const uint8_t* req, uint16_t req_len,
2097 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
2099 if (!req || !resp || resp_cap < 2u)
2105 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::JTAG_CONFIGURE);
2109 if (
jtag_ ==
nullptr)
2121 const uint8_t count = req[1];
2122 if (count > JTAG_MAX_DEVICES || req_len <
static_cast<uint16_t
>(2u + count))
2131 for (uint32_t i = 0; i < count; ++i)
2133 const uint8_t len = req[
static_cast<uint16_t
>(2u + i)];
2150 ErrorCode HandleJTAGIdCode(
bool ,
const uint8_t* req, uint16_t req_len,
2151 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
2153 if (!req || !resp || resp_cap < 6u)
2159 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::JTAG_IDCODE);
2163 if (
jtag_ ==
nullptr ||
2174 const uint8_t index = req[1];
2181 LibXR::Debug::JtagProtocol::UpdateChainCache(
jtag_chain_);
2184 uint32_t idcode = 0u;
2187 (idcode == 0u || idcode == 0xFFFF'FFFFu || ((idcode & 0x1u) == 0u)) &&
2190 uint32_t fallback_idcode = 0u;
2191 ec = dp.ReadIdCodeWithIr(0x01u, fallback_idcode);
2196 if (fallback_idcode != 0u && fallback_idcode != 0xFFFF'FFFFu &&
2197 ((fallback_idcode & 0x1u) != 0u))
2199 idcode = fallback_idcode;
2217 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
2219 if (!req || req_len < 2u)
2221 return BuildCmdStatusResponse(
2222 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS),
DAP_ERROR, resp,
2226 const uint8_t NUM = req[1];
2229 return BuildCmdStatusResponse(
2230 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS),
DAP_OK, resp,
2234 uint16_t req_off = 2u;
2235 for (uint32_t i = 0u; i < NUM; ++i)
2237 if (req_off >= req_len)
2239 return BuildCmdStatusResponse(
2240 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS),
DAP_ERROR, resp,
2244 uint16_t cmd_len = 0u;
2246 static_cast<uint16_t
>(req_len - req_off), cmd_len) ||
2249 return BuildCmdStatusResponse(
2250 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS),
DAP_ERROR, resp,
2253 req_off =
static_cast<uint16_t
>(req_off + cmd_len);
2256 if (req_off != req_len)
2258 return BuildCmdStatusResponse(
2259 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS),
DAP_ERROR, resp,
2263 if (
static_cast<uint32_t
>(queued_request_length_) +
2264 static_cast<uint32_t
>(req_len - 2u) >
2265 static_cast<uint32_t
>(QUEUED_REQ_BUFFER_SIZE) ||
2266 static_cast<uint32_t
>(queued_command_count_) +
static_cast<uint32_t
>(NUM) >
2267 static_cast<uint32_t
>(QUEUED_CMD_COUNT_MAX))
2269 return BuildCmdStatusResponse(
2270 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS),
DAP_ERROR, resp,
2276 queued_request_length_ =
2277 static_cast<uint16_t
>(queued_request_length_ + (req_len - 2u));
2278 queued_command_count_ =
static_cast<uint16_t
>(queued_command_count_ + NUM);
2280 return BuildCmdStatusResponse(
2281 ToU8(LibXR::USB::DapLinkV2Def::CommandId::QUEUE_COMMANDS),
DAP_OK, resp, resp_cap,
2289 uint16_t , uint8_t* resp, uint16_t resp_cap,
2293 ResetQueuedCommandState();
2297 return BuildCmdStatusResponse(
2298 ToU8(LibXR::USB::DapLinkV2Def::CommandId::EXECUTE_COMMANDS),
DAP_ERROR, resp,
2310 uint8_t MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack)
const
2312 static constexpr uint8_t ACK_MAP[8] = {7u, 1u, 2u, 7u, 4u, 7u, 7u, 7u};
2313 return ACK_MAP[
static_cast<uint8_t
>(ack) & 0x07u];
2316 uint8_t MapAckToDapResp(LibXR::Debug::JtagProtocol::Ack ack)
const
2320 case LibXR::Debug::JtagProtocol::Ack::OK:
2322 case LibXR::Debug::JtagProtocol::Ack::WAIT:
2324 case LibXR::Debug::JtagProtocol::Ack::FAULT:
2326 case LibXR::Debug::JtagProtocol::Ack::NO_ACK:
2327 case LibXR::Debug::JtagProtocol::Ack::PROTOCOL:
2333 static inline uint16_t LoadU16Le(
const uint8_t* p)
2335 return static_cast<uint16_t
>(
2336 static_cast<uint16_t
>(p[0]) |
2337 static_cast<uint16_t
>(
static_cast<uint16_t
>(p[1]) << 8u));
2340 static inline void StoreU16Le(uint8_t* p, uint16_t v)
2342 p[0] =
static_cast<uint8_t
>(v & 0xFFu);
2343 p[1] =
static_cast<uint8_t
>((v >> 8u) & 0xFFu);
2346 static inline uint32_t LoadU32Le(
const uint8_t* p)
2348 return static_cast<uint32_t
>(
2349 static_cast<uint32_t
>(p[0]) | (
static_cast<uint32_t
>(p[1]) << 8u) |
2350 (
static_cast<uint32_t
>(p[2]) << 16u) | (
static_cast<uint32_t
>(p[3]) << 24u));
2353 static inline void StoreU32Le(uint8_t* p, uint32_t v)
2355 p[0] =
static_cast<uint8_t
>(v & 0xFFu);
2356 p[1] =
static_cast<uint8_t
>((v >> 8u) & 0xFFu);
2357 p[2] =
static_cast<uint8_t
>((v >> 16u) & 0xFFu);
2358 p[3] =
static_cast<uint8_t
>((v >> 24u) & 0xFFu);
2370 if (resp.
ack == LibXR::Debug::SwdProtocol::Ack::WAIT)
2372 return swd_.TransferWithRetry(req, resp);
2375 if (resp.
ack == LibXR::Debug::SwdProtocol::Ack::FAULT)
2377 const auto POL =
swd_.GetTransferPolicy();
2378 if (POL.clear_sticky_on_fault)
2380 LibXR::Debug::SwdProtocol::Ack abort_ack =
2381 LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2382 (void)
swd_.WriteAbort(LibXR::Debug::SwdProtocol::DP_ABORT_STKCMPCLR |
2383 LibXR::Debug::SwdProtocol::DP_ABORT_STKERRCLR |
2384 LibXR::Debug::SwdProtocol::DP_ABORT_WDERRCLR |
2385 LibXR::Debug::SwdProtocol::DP_ABORT_ORUNERRCLR,
2393 ErrorCode DpReadRdbuffFast(uint32_t& val, LibXR::Debug::SwdProtocol::Ack& ack_out)
2396 const auto req = LibXR::Debug::SwdProtocol::make_dp_read_req(
2397 LibXR::Debug::SwdProtocol::DpReadReg::RDBUFF);
2398 const ErrorCode ec = TransferTxnFast(req, swd_resp);
2399 ack_out = swd_resp.
ack;
2404 if (swd_resp.
ack != LibXR::Debug::SwdProtocol::Ack::OK || !swd_resp.
parity_ok)
2408 val = swd_resp.
rdata;
2412 ErrorCode CompletePendingApReadFast(uint32_t& val,
2413 LibXR::Debug::SwdProtocol::Ack& ack_out)
2415 return DpReadRdbuffFast(val, ack_out);
2418 ErrorCode CheckPostedApWriteFast(LibXR::Debug::SwdProtocol::Ack& ack_out)
2421 const auto req = LibXR::Debug::SwdProtocol::make_dp_read_req(
2422 LibXR::Debug::SwdProtocol::DpReadReg::CTRL_STAT);
2423 const ErrorCode ec = TransferTxnFast(req, swd_resp);
2424 ack_out = swd_resp.
ack;
2429 if (swd_resp.
ack != LibXR::Debug::SwdProtocol::Ack::OK || !swd_resp.
parity_ok)
2436 ErrorCode ApReadPostedFast(uint8_t addr2b, uint32_t& posted,
2437 LibXR::Debug::SwdProtocol::Ack& ack_out)
2440 const auto req = LibXR::Debug::SwdProtocol::make_ap_read_req(addr2b);
2441 const ErrorCode ec = TransferTxnFast(req, swd_resp);
2442 ack_out = swd_resp.
ack;
2447 if (swd_resp.
ack != LibXR::Debug::SwdProtocol::Ack::OK || !swd_resp.
parity_ok)
2451 posted = swd_resp.
rdata;
2464 ErrorCode HandleTransfer(
bool in_isr,
const uint8_t* req, uint16_t req_len,
2465 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
2468 if (!req || !resp || resp_cap < 3u)
2473 if constexpr (JTAG_ENABLED)
2477 return HandleJtagTransfer(in_isr, req, req_len, resp, resp_cap, out_len);
2481 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER);
2484 uint16_t resp_off = 3u;
2489 resp[2] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2497 resp[2] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2502 const uint8_t COUNT = req[2];
2503 uint16_t req_off = 3u;
2505 auto push_u32 = [&](uint32_t v) ->
bool
2507 if (resp_off + 4u > resp_cap)
2512 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
2516 auto push_timestamp = [&]() ->
bool
2522 auto ensure_space = [&](uint16_t bytes) ->
bool
2523 {
return (resp_off + bytes) <= resp_cap; };
2525 auto bytes_for_read = [&](
bool need_ts) -> uint16_t
2526 {
return static_cast<uint16_t
>(need_ts ? 8u : 4u); };
2528 uint8_t response_count = 0u;
2530 uint8_t response_value = 0u;
2534 bool pending_ap_write =
false;
2537 struct PendingApRead
2540 bool need_ts =
false;
2543 auto emit_read_with_ts = [&](
bool need_ts, uint32_t data) ->
bool
2547 if (!push_timestamp())
2552 if (!push_u32(data))
2562 auto complete_pending_ap_read = [&]() ->
bool
2569 if (!ensure_space(bytes_for_read(pending.need_ts)))
2571 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2575 uint32_t rdata = 0u;
2576 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2577 const ErrorCode EC = CompletePendingApReadFast(rdata, ack);
2579 const uint8_t V = MapAckToDapResp(ack);
2580 if (V != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2587 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2591 if (!emit_read_with_ts(pending.need_ts, rdata))
2593 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2597 pending.valid =
false;
2598 pending.need_ts =
false;
2601 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2605 auto check_posted_ap_write_if_pending = [&]() ->
bool
2607 if (!pending_ap_write)
2611 LibXR::Debug::SwdProtocol::Ack check_ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2612 const ErrorCode check_ec = CheckPostedApWriteFast(check_ack);
2613 response_value = MapAckToDapResp(check_ack);
2614 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2620 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2623 pending_ap_write =
false;
2628 auto complete_pending_ap_read_if_any = [&]() ->
bool
2629 {
return pending.valid ? complete_pending_ap_read() : true; };
2631 auto close_posted_state = [&]() ->
bool
2632 {
return complete_pending_ap_read_if_any() && check_posted_ap_write_if_pending(); };
2635 for (uint32_t i = 0; i < COUNT; ++i)
2637 if (req_off >= req_len)
2639 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2643 const uint8_t RQ = req[req_off++];
2650 const bool MATCH_VALUE =
2651 ((RQ & LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
2652 const bool MATCH_MASK =
2653 ((RQ & LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_MASK) != 0u);
2656 if (TS && (MATCH_VALUE || MATCH_MASK))
2658 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2662 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2670 if (!complete_pending_ap_read_if_any())
2675 if (req_off + 4u > req_len)
2677 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2681 uint32_t wdata = LoadU32Le(&req[req_off]);
2682 req_off =
static_cast<uint16_t
>(req_off + 4u);
2687 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2693 ec =
swd_.ApWriteTxn(ADDR2B, wdata, ack);
2697 ec =
swd_.DpWriteTxn(
static_cast<LibXR::Debug::SwdProtocol::DpWriteReg
>(ADDR2B),
2701 response_value = MapAckToDapResp(ack);
2702 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2708 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2714 pending_ap_write =
true;
2719 if (!push_timestamp())
2721 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2736 if (!close_posted_state())
2741 if (req_off + 4u > req_len)
2743 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2747 uint32_t match_val = LoadU32Le(&req[req_off]);
2748 req_off =
static_cast<uint16_t
>(req_off + 4u);
2750 uint32_t rdata = 0u;
2752 bool matched =
false;
2758 ec =
swd_.ApReadTxn(ADDR2B, rdata, ack);
2759 if (ec ==
ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
2766 ec =
swd_.DpReadTxn(
2767 static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B), rdata, ack);
2770 response_value = MapAckToDapResp(ack);
2771 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2777 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2794 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2802 static_cast<uint8_t
>(LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK |
2803 LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MISMATCH);
2808 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2817 if (!close_posted_state())
2822 uint32_t rdata = 0u;
2823 ec =
swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
2826 response_value = MapAckToDapResp(ack);
2827 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2833 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2837 if (!ensure_space(bytes_for_read(TS)))
2839 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2843 if (!emit_read_with_ts(TS, rdata))
2845 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2849 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2855 if (!check_posted_ap_write_if_pending())
2865 uint32_t dummy_posted = 0u;
2866 ec = ApReadPostedFast(ADDR2B, dummy_posted, ack);
2868 response_value = MapAckToDapResp(ack);
2869 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2875 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2881 pending.valid =
true;
2882 pending.need_ts = TS;
2886 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2892 if (!ensure_space(bytes_for_read(pending.need_ts)))
2894 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2898 uint32_t posted_prev = 0u;
2899 ec = ApReadPostedFast(ADDR2B, posted_prev, ack);
2901 const uint8_t CUR_V = MapAckToDapResp(ack);
2902 if (CUR_V != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK || ec !=
ErrorCode::OK)
2906 const uint8_t PROOR_FAIL =
2907 (CUR_V != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2909 :
LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2911 if (!complete_pending_ap_read())
2919 response_value = PROOR_FAIL;
2925 if (!emit_read_with_ts(pending.need_ts, posted_prev))
2927 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
2931 pending.valid =
true;
2932 pending.need_ts = TS;
2934 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
2951 const uint8_t PRIOR_FAIL = response_value;
2953 if (!complete_pending_ap_read())
2961 if (PRIOR_FAIL != 0u && PRIOR_FAIL != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
2963 response_value = PRIOR_FAIL;
2968 if (response_value == LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK &&
2969 !check_posted_ap_write_if_pending())
2973 resp[1] = response_count;
2974 resp[2] = response_value;
2978 ErrorCode HandleTransferBlock(
bool in_isr,
const uint8_t* req, uint16_t req_len,
2979 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
2981 if constexpr (JTAG_ENABLED)
2985 return HandleJtagTransferBlock(in_isr, req, req_len, resp, resp_cap, out_len);
2991 if (!resp || resp_cap < 4u)
2997 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_BLOCK);
3003 if (!req || req_len < 5u)
3005 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3012 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3016 uint16_t count = 0u;
3017 count = LoadU16Le(&req[2]);
3019 const uint8_t DAP_RQ = req[4];
3022 if ((DAP_RQ & (LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_VALUE |
3023 LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
3025 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3030 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3037 const uint16_t DONE0 = 0u;
3038 StoreU16Le(&resp[1], DONE0);
3039 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
3051 uint16_t req_off = 5u;
3052 uint16_t resp_off = 4u;
3057 const uint32_t REQ_NEED =
3058 static_cast<uint32_t
>(req_off) + (
static_cast<uint32_t
>(count) * 4u);
3059 if (REQ_NEED > req_len)
3061 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3062 StoreU16Le(&resp[1], done);
3069 auto swd_req = LibXR::Debug::SwdProtocol::make_ap_write_req(ADDR2B, 0u);
3071 for (uint32_t i = 0; i < count; ++i)
3073 uint32_t wdata = LoadU32Le(&req[req_off]);
3074 req_off =
static_cast<uint16_t
>(req_off + 4u);
3075 swd_req.wdata = wdata;
3076 const ErrorCode ec = TransferTxnFast(swd_req, swd_resp);
3077 xresp = MapAckToDapResp(swd_resp.
ack);
3078 if (swd_resp.
ack != LibXR::Debug::SwdProtocol::Ack::OK)
3084 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3087 done =
static_cast<uint16_t
>(i + 1u);
3089 if (xresp == LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK && done != 0u)
3091 LibXR::Debug::SwdProtocol::Ack check_ack =
3092 LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
3093 const ErrorCode check_ec = CheckPostedApWriteFast(check_ack);
3094 xresp = MapAckToDapResp(check_ack);
3095 if (check_ack == LibXR::Debug::SwdProtocol::Ack::OK &&
3098 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3104 for (uint32_t i = 0; i < count; ++i)
3106 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
3108 uint32_t wdata = LoadU32Le(&req[req_off]);
3109 req_off =
static_cast<uint16_t
>(req_off + 4u);
3110 ec =
swd_.DpWriteTxn(
static_cast<LibXR::Debug::SwdProtocol::DpWriteReg
>(ADDR2B),
3112 xresp = MapAckToDapResp(ack);
3113 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
3119 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3122 done =
static_cast<uint16_t
>(i + 1u);
3125 StoreU16Le(&resp[1], done);
3134 const uint32_t RESP_NEED =
3135 static_cast<uint32_t
>(resp_off) + (
static_cast<uint32_t
>(count) * 4u);
3136 if (RESP_NEED > resp_cap)
3138 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3139 StoreU16Le(&resp[1], done);
3146 for (uint32_t i = 0; i < count; ++i)
3148 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
3150 uint32_t rdata = 0u;
3151 ec =
swd_.DpReadTxn(
static_cast<LibXR::Debug::SwdProtocol::DpReadReg
>(ADDR2B),
3153 xresp = MapAckToDapResp(ack);
3154 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
3160 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3163 StoreU32Le(&resp[resp_off], rdata);
3164 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
3165 done =
static_cast<uint16_t
>(i + 1u);
3167 StoreU16Le(&resp[1], done);
3175 const uint32_t RESP_NEED =
3176 static_cast<uint32_t
>(resp_off) + (
static_cast<uint32_t
>(count) * 4u);
3177 if (RESP_NEED > resp_cap)
3179 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3180 StoreU16Le(&resp[1], done);
3186 auto ap_read_req = LibXR::Debug::SwdProtocol::make_ap_read_req(ADDR2B);
3188 ErrorCode ec = TransferTxnFast(ap_read_req, ap_read_resp);
3189 xresp = MapAckToDapResp(ap_read_resp.
ack);
3190 if (ap_read_resp.
ack != LibXR::Debug::SwdProtocol::Ack::OK)
3196 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3201 for (uint32_t i = 1; i < count; ++i)
3203 ec = TransferTxnFast(ap_read_req, ap_read_resp);
3204 const uint8_t CUR = MapAckToDapResp(ap_read_resp.
ack);
3206 if (ap_read_resp.
ack != LibXR::Debug::SwdProtocol::Ack::OK ||
3210 if (resp_off + 4u <= resp_cap)
3212 uint32_t rdbuff_data = 0u;
3213 LibXR::Debug::SwdProtocol::Ack rdbuff_ack =
3214 LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
3215 const ErrorCode ec2 = CompletePendingApReadFast(rdbuff_data, rdbuff_ack);
3216 const uint8_t v2 = MapAckToDapResp(rdbuff_ack);
3218 if (v2 == LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK && ec2 ==
ErrorCode::OK)
3220 StoreU32Le(&resp[resp_off], rdbuff_data);
3221 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
3222 done =
static_cast<uint16_t
>(i);
3229 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3238 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3243 StoreU32Le(&resp[resp_off], ap_read_resp.
rdata);
3244 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
3245 done =
static_cast<uint16_t
>(i);
3251 uint32_t rdbuff_data = 0u;
3252 LibXR::Debug::SwdProtocol::Ack rdbuff_ack =
3253 LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
3254 const ErrorCode ec2 = CompletePendingApReadFast(rdbuff_data, rdbuff_ack);
3255 const uint8_t v2 = MapAckToDapResp(rdbuff_ack);
3258 if (v2 != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3264 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3268 StoreU32Le(&resp[resp_off], rdbuff_data);
3269 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
3274 StoreU16Le(&resp[1], done);
3281 ErrorCode HandleJtagTransfer(
bool ,
const uint8_t* req, uint16_t req_len,
3282 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
3285 if (!req || !resp || resp_cap < 3u)
3290 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER);
3293 uint16_t resp_off = 3u;
3297 resp[2] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3305 resp[2] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3310 const uint8_t TAP_INDEX = req[1];
3313 resp[2] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3319 LibXR::Debug::JtagProtocol::UpdateChainCache(
jtag_chain_);
3322 const uint8_t COUNT = req[2];
3323 uint16_t req_off = 3u;
3325 auto push_u32 = [&](uint32_t v) ->
bool
3327 if (resp_off + 4u > resp_cap)
3332 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
3336 auto push_timestamp = [&]() ->
bool
3342 auto ensure_space = [&](uint16_t bytes) ->
bool
3343 {
return (resp_off + bytes) <= resp_cap; };
3345 auto bytes_for_read = [&](
bool need_ts) -> uint16_t
3346 {
return static_cast<uint16_t
>(need_ts ? 8u : 4u); };
3348 auto idle_after_attempt = [&]()
3356 auto dp_read_retry = [&](uint8_t addr2b, uint32_t& val,
3357 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3362 const ErrorCode ec = dp.DpReadTxn(addr2b, val, ack);
3363 idle_after_attempt();
3364 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3373 auto dp_write_retry = [&](uint8_t addr2b, uint32_t val,
3374 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3379 const ErrorCode ec = dp.DpWriteTxn(addr2b, val, ack);
3380 idle_after_attempt();
3381 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3390 auto ap_read_retry = [&](uint8_t addr2b, uint32_t& val,
3391 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3396 const ErrorCode ec = dp.ApReadTxn(addr2b, val, ack);
3397 idle_after_attempt();
3398 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3407 auto ap_write_retry = [&](uint8_t addr2b, uint32_t val,
3408 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3413 const ErrorCode ec = dp.ApWriteTxn(addr2b, val, ack);
3414 idle_after_attempt();
3415 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3424 auto check_posted_ap_write_jtag =
3425 [&](LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3427 uint32_t ctrl_stat = 0u;
3428 return dp_read_retry(
3429 static_cast<uint8_t
>(LibXR::Debug::SwdProtocol::DpReadReg::CTRL_STAT),
3433 uint8_t response_count = 0u;
3434 uint8_t response_value = 0u;
3435 bool pending_ap_write =
false;
3437 auto emit_read_with_ts = [&](
bool need_ts, uint32_t data) ->
bool
3441 if (!push_timestamp())
3446 if (!push_u32(data))
3454 auto check_posted_ap_write_if_pending = [&]() ->
bool
3456 if (!pending_ap_write)
3461 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
3462 const ErrorCode ec = check_posted_ap_write_jtag(ack);
3463 const uint8_t v = MapAckToDapResp(ack);
3465 if (v != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3472 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3476 pending_ap_write =
false;
3480 auto should_check_pending_ap_write_at_tail = [&]() ->
bool
3482 return response_value == LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK ||
3484 static_cast<uint8_t
>(LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK |
3485 LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MISMATCH);
3488 for (uint32_t i = 0; i < COUNT; ++i)
3490 if (req_off >= req_len)
3492 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3496 const uint8_t RQ = req[req_off++];
3501 const bool MATCH_VALUE =
3502 ((RQ & LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
3503 const bool MATCH_MASK =
3504 ((RQ & LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_MASK) != 0u);
3506 if (TS && (MATCH_VALUE || MATCH_MASK))
3508 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3512 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
3517 if (req_off + 4u > req_len)
3519 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3523 uint32_t wdata = 0u;
3525 req_off =
static_cast<uint16_t
>(req_off + 4u);
3530 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
3537 ec = ap_write_retry(ADDR2B, wdata, ack);
3541 ec = dp_write_retry(ADDR2B, wdata, ack);
3544 response_value = MapAckToDapResp(ack);
3545 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3551 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3557 if (!push_timestamp())
3559 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3567 pending_ap_write =
true;
3574 if (!check_posted_ap_write_if_pending())
3579 if (req_off + 4u > req_len)
3581 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3585 uint32_t match_val = 0u;
3587 req_off =
static_cast<uint16_t
>(req_off + 4u);
3589 uint32_t rdata = 0u;
3591 bool matched =
false;
3597 ec = ap_read_retry(ADDR2B, rdata, ack);
3601 ec = dp_read_retry(ADDR2B, rdata, ack);
3604 response_value = MapAckToDapResp(ack);
3605 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3611 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3628 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3636 static_cast<uint8_t
>(LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK |
3637 LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MISMATCH);
3647 if (!check_posted_ap_write_if_pending())
3652 uint32_t rdata = 0u;
3653 ec = dp_read_retry(ADDR2B, rdata, ack);
3655 response_value = MapAckToDapResp(ack);
3656 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3662 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3666 if (!ensure_space(bytes_for_read(TS)))
3668 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3672 if (!emit_read_with_ts(TS, rdata))
3674 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3678 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
3682 uint32_t rdata = 0u;
3683 if (!check_posted_ap_write_if_pending())
3688 ec = ap_read_retry(ADDR2B, rdata, ack);
3690 response_value = MapAckToDapResp(ack);
3691 if (response_value != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3697 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3701 if (!ensure_space(bytes_for_read(TS)))
3703 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3707 if (!emit_read_with_ts(TS, rdata))
3709 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3713 response_value = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
3723 if (pending_ap_write && should_check_pending_ap_write_at_tail())
3725 const uint8_t PRIOR_RESPONSE = response_value;
3726 if (check_posted_ap_write_if_pending())
3728 response_value = PRIOR_RESPONSE;
3732 resp[1] = response_count;
3733 resp[2] = response_value;
3738 ErrorCode HandleJtagTransferBlock(
bool ,
const uint8_t* req, uint16_t req_len,
3739 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
3741 if (!req || !resp || resp_cap < 4u)
3747 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::TRANSFER_BLOCK);
3755 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3762 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3766 const uint8_t TAP_INDEX = req[1];
3769 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3774 LibXR::Debug::JtagProtocol::UpdateChainCache(
jtag_chain_);
3776 uint16_t count = 0u;
3778 const uint8_t DAP_RQ = req[4];
3780 if ((DAP_RQ & (LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_VALUE |
3781 LibXR::USB::DapLinkV2Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
3783 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3788 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3794 const uint16_t DONE0 = 0u;
3796 resp[3] = LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK;
3802 auto idle_after_attempt = [&]()
3810 auto dp_read_retry = [&](uint8_t addr2b, uint32_t& val,
3811 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3816 const ErrorCode ec = dp.DpReadTxn(addr2b, val, ack);
3817 idle_after_attempt();
3818 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3827 auto dp_write_retry = [&](uint8_t addr2b, uint32_t val,
3828 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3833 const ErrorCode ec = dp.DpWriteTxn(addr2b, val, ack);
3834 idle_after_attempt();
3835 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3844 auto ap_read_retry = [&](uint8_t addr2b, uint32_t& val,
3845 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3850 const ErrorCode ec = dp.ApReadTxn(addr2b, val, ack);
3851 idle_after_attempt();
3852 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3861 auto ap_write_retry = [&](uint8_t addr2b, uint32_t val,
3862 LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3867 const ErrorCode ec = dp.ApWriteTxn(addr2b, val, ack);
3868 idle_after_attempt();
3869 if (ack != LibXR::Debug::JtagProtocol::Ack::WAIT || retry == 0u ||
3878 auto check_posted_ap_write_jtag =
3879 [&](LibXR::Debug::JtagProtocol::Ack& ack) ->
ErrorCode
3881 uint32_t ctrl_stat = 0u;
3882 return dp_read_retry(
3883 static_cast<uint8_t
>(LibXR::Debug::SwdProtocol::DpReadReg::CTRL_STAT),
3893 uint16_t req_off = 5u;
3894 uint16_t resp_off = 4u;
3898 for (uint32_t i = 0; i < count; ++i)
3900 if (req_off + 4u > req_len)
3902 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3906 uint32_t wdata = 0u;
3908 req_off =
static_cast<uint16_t
>(req_off + 4u);
3910 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
3912 AP ? ap_write_retry(ADDR2B, wdata, ack) : dp_write_retry(ADDR2B, wdata, ack);
3914 xresp = MapAckToDapResp(ack);
3917 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3921 if (ack != LibXR::Debug::JtagProtocol::Ack::OK)
3928 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3932 done =
static_cast<uint16_t
>(i + 1u);
3935 if (AP && xresp == LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK && done > 0u)
3937 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
3938 const ErrorCode ec = check_posted_ap_write_jtag(ack);
3939 const uint8_t v = MapAckToDapResp(ack);
3940 if (v != LibXR::USB::DapLinkV2Def::DAP_TRANSFER_OK)
3946 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3956 for (uint32_t i = 0; i < count; ++i)
3958 if (resp_off + 4u > resp_cap)
3960 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3964 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
3966 uint32_t rdata = 0u;
3970 ec = ap_read_retry(ADDR2B, rdata, ack);
3974 ec = dp_read_retry(ADDR2B, rdata, ack);
3977 xresp = MapAckToDapResp(ack);
3980 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3984 if (ack != LibXR::Debug::JtagProtocol::Ack::OK)
3991 xresp |= LibXR::USB::DapLinkV2Def::DAP_TRANSFER_ERROR;
3996 resp_off =
static_cast<uint16_t
>(resp_off + 4u);
3997 done =
static_cast<uint16_t
>(i + 1u);
4006 ErrorCode HandleJtagWriteAbort(
bool ,
const uint8_t* req, uint16_t req_len,
4007 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len)
4009 if (!req || !resp || resp_cap < 2u)
4015 resp[0] = ToU8(LibXR::USB::DapLinkV2Def::CommandId::WRITE_ABORT);
4024 const uint8_t TAP_INDEX = req[1];
4031 LibXR::Debug::JtagProtocol::UpdateChainCache(
jtag_chain_);
4033 uint32_t flags = 0u;
4037 LibXR::Debug::JtagProtocol::Ack ack = LibXR::Debug::JtagProtocol::Ack::PROTOCOL;
4038 const ErrorCode ec = dp.WriteAbort(flags, ack);
4039 if (ec ==
ErrorCode::OK && ack == LibXR::Debug::JtagProtocol::Ack::OK)
4051 void DriveReset(
bool release)
4058 swj_shadow_ |= LibXR::USB::DapLinkV2Def::DAP_SWJ_NRESET;
4072 void ResetJtagChainState()
4074 if constexpr (JTAG_ENABLED)
4087 void DelayUsIfAllowed(
bool , uint32_t us)
4093 static constexpr uint16_t DEFAULT_DAP_PACKET_SIZE = DefaultDapPacketSize;
4094 static constexpr uint8_t PACKET_COUNT_ADVERTISED = AdvertisedPacketCount;
4095 static constexpr uint8_t PACKET_COUNT_EFFECTIVE =
4096 (PACKET_COUNT_ADVERTISED > 4u) ? 4u : PACKET_COUNT_ADVERTISED;
4097 static constexpr uint8_t MAX_OUTSTANDING_RESPONSES = PACKET_COUNT_EFFECTIVE;
4101 static constexpr uint16_t OPENOCD_SAFE_DAP_PACKET_SIZE =
4102 static_cast<uint16_t
>((255u * 5u) + 4u);
4103 static constexpr uint8_t JTAG_MAX_DEVICES = 16u;
4106 static constexpr uint16_t MAX_DAP_PACKET_SIZE = MaxDapPacketSize;
4107 static constexpr uint16_t QUEUED_REQ_BUFFER_SIZE = QueuedRequestBufferSize;
4108 static constexpr uint16_t QUEUED_CMD_COUNT_MAX = QueuedCommandCountMax;
4109 static constexpr uint16_t RESP_SLOT_SIZE = MAX_DAP_PACKET_SIZE;
4110 static constexpr uint8_t RESP_QUEUE_DEPTH = PACKET_COUNT_EFFECTIVE;
4111 static constexpr uint16_t QUEUED_REQ_BUFFER_ALLOC_SIZE = QUEUED_REQ_BUFFER_SIZE;
4112 static_assert(PACKET_COUNT_ADVERTISED > 0u,
"PACKET_COUNT_ADVERTISED must be > 0");
4113 static_assert(PACKET_COUNT_EFFECTIVE > 0u,
"PACKET_COUNT_EFFECTIVE must be > 0");
4114 static_assert(MAX_DAP_PACKET_SIZE >= DEFAULT_DAP_PACKET_SIZE,
4115 "MAX_DAP_PACKET_SIZE must be >= DEFAULT_DAP_PACKET_SIZE");
4116 static_assert(MAX_DAP_PACKET_SIZE <= OPENOCD_SAFE_DAP_PACKET_SIZE,
4117 "MAX_DAP_PACKET_SIZE exceeds OpenOCD-safe limit");
4118 static_assert(((OPENOCD_SAFE_DAP_PACKET_SIZE - 4u) / 5u) <= 255u,
4119 "OPENOCD_SAFE_DAP_PACKET_SIZE too large for CMD_DAP_TFER u8 count");
4120 static_assert(QUEUED_REQ_BUFFER_SIZE > 0u,
"QUEUED_REQ_BUFFER_SIZE must be > 0");
4121 static_assert(QUEUED_CMD_COUNT_MAX > 0u,
"QUEUED_CMD_COUNT_MAX must be > 0");
4122 static_assert(RESP_SLOT_SIZE >= DEFAULT_DAP_PACKET_SIZE,
4123 "RESP_SLOT_SIZE must cover FS bulk packet size");
4124 static_assert((RESP_QUEUE_DEPTH & (RESP_QUEUE_DEPTH - 1u)) == 0u,
4125 "Response queue depth must be power-of-two");
4133 static_cast<uint16_t
>(LibXR::USB::WinUsbMsOs20::GUID_STR_UTF16_BYTES +
4139 uint8_t payload[RESP_SLOT_SIZE] = {};
4143 uint8_t resp_q_head_ = 0u;
4144 uint8_t resp_q_tail_ = 0u;
4145 uint8_t resp_q_count_ = 0u;
4146 bool deferred_in_resp_valid_ =
false;
4147 uint16_t deferred_in_resp_len_ = 0u;
4149 uint8_t queued_request_buffer_[QUEUED_REQ_BUFFER_ALLOC_SIZE] = {};
4150 uint16_t queued_request_length_ = 0u;
4151 uint16_t queued_command_count_ = 0u;
4153 uint8_t out_req_multi_storage_[MAX_DAP_PACKET_SIZE] = {};
4154 LibXR::RawData out_req_multi_buf_{out_req_multi_storage_, DEFAULT_DAP_PACKET_SIZE};
4155 uint8_t in_tx_multi_storage_[MAX_DAP_PACKET_SIZE] = {};
4156 LibXR::RawData in_tx_multi_buf_{in_tx_multi_storage_, DEFAULT_DAP_PACKET_SIZE};
4179 uint8_t
name[LibXR::USB::WinUsbMsOs20::
4180 PROP_NAME_DEVICE_INTERFACE_GUIDS_BYTES];
4198 DapLinkV2Def::DAP_SWJ_SWDIO_TMS |
4199 DapLinkV2Def::DAP_SWJ_NRESET);
4205 "XRDAP",
"XRobot",
"DAP_DEMO",
"0.1.0"};