DAPLinkV1 设备协议栈
本文档描述 XRUSB 的 CMSIS-DAP v1(HID)设备类实现:LibXR::USB::DapLinkV1Class<SwdPort>。
该设备类面向仍通过 HID Report 传输的 CMSIS-DAP v1 主机工具链。支持 SWD;调用 SetJtag() 提供 JTAG 后端后也支持 JTAG。另外支持常见 DAP 核心命令、SWJ/SWD/JTAG 序列和可选的 nRESET GPIO 控制。
支持能力概览:
- CMSIS-DAP v1 HID transport
- SWD;设置 JTAG 后端后
DAP_Connect也可连接 JTAG - 可选 nRESET 控制(通过
GPIO* nreset_gpio注入) - HID Interrupt IN/OUT 传输
- DAP_Transfer / DAP_TransferBlock(含 AP posted-read pipeline)
1. 类与构造方式
1.1 LibXR::USB::DapLinkV1Class<SwdPort>
该类为模板类,模板参数 SwdPort 提供底层 SWD 能力。
构造函数:
template <typename SwdPort>
explicit DapLinkV1Class(
Endpoint::EPNumber in_ep_num,
Endpoint::EPNumber out_ep_num,
SwdPort& swd_link,
LibXR::GPIO* nreset_gpio = nullptr);
参数说明:
in_ep_num/out_ep_num:HID Interrupt IN/OUT 端点号(必填)swd_link:SWD 链路对象引用nreset_gpio:可选 nRESET GPIO
接口字符串固定为 "CMSIS-DAP"。
常用接口:
SetInfoStrings(info):覆盖DAP_Info字符串GetState():读取内部 DAP 状态IsInited():是否已完成绑定初始化SetJtag(jtag):设置 JTAG 后端(LibXR::Debug::Jtag*)。包含daplink_v1_profile_swd.hpp时 JTAG 在编译期关闭,SetJtag()不起作用;直接包含daplink_v1.hpp或daplink_v1_profile_jtag.hpp时 JTAG 可用
1.2 InfoStrings
DAP_Info 字符串集合:
struct InfoStrings
{
const char* vendor;
const char* product;
const char* serial;
const char* firmware_ver;
const char* device_vendor;
const char* device_name;
const char* board_vendor;
const char* board_name;
const char* product_fw_ver;
};
2. 传输模型与 HID 报告
DapLinkV1Class 继承自:
HID<sizeof(DAPLINK_V1_REPORT_DESC), DapLinkV1Def::MAX_REQUEST_SIZE,
DapLinkV1Def::MAX_RESPONSE_SIZE>
常量:
MAX_REQUEST_SIZE = 64MAX_RESPONSE_SIZE = 64
HID 报告描述符定义了:
- 64 字节 Input Report
- 64 字节 Output Report
- 64 字节 Feature Report
请求和响应通过 HID Interrupt OUT / IN 传输。描述符中的 Feature Report 未实现:GET_REPORT(Feature) 返回空数据,SET_REPORT 返回不支持。
3. 生命周期:Bind / Unbind
3.1 Bind
绑定阶段主要完成:
- 调用 HID 基类绑定并申请 IN/OUT 端点
- 初始化 DAP 运行态:
debug_port = DISABLEDtransfer_abort = falseswj_clock_hz = 1MHz- SWJ shadow 默认:SWDIO=1、nRESET=1、SWCLK=0
- arm OUT 接收,准备处理主机 HID Output Report
3.2 Unbind
解绑阶段主要完成:
- 关闭 SWD 后端
- 释放 HID IN/OUT 端点
- 复位 shadow 状态(SWDIO=1、nRESET=1)
4. DAP_Info 关键字段
当前实现中,关键 DAP_Info 字段行为为:
CAPABILITIES:DAP_CAP_SWD;设置了 JTAG 后端时加上DAP_CAP_JTAGPACKET_COUNT:1PACKET_SIZE:64TIMESTAMP_CLOCK:1,000,000
说明:
PACKET_SIZE与 HID v1 的固定 64-byte report 长度一致- 与 DAPLinkV2 不同,这里没有可变的 Bulk packet-size 暴露语义
5. 支持的命令范围
支持的命令:
DAP_InfoDAP_HostStatusDAP_Connect/DAP_DisconnectDAP_TransferConfigureDAP_TransferDAP_TransferBlockDAP_TransferAbortDAP_WriteABORTDAP_DelayDAP_ResetTargetDAP_SWJ_PinsDAP_SWJ_ClockDAP_SWJ_SequenceDAP_SWD_ConfigureDAP_SWD_SequenceDAP_JTAG_Sequence/DAP_JTAG_Configure/DAP_JTAG_IDCODE(JTAG 可用时)DAP_QueueCommands/DAP_ExecuteCommands:返回<CMD, DAP_ERROR>
实现边界:
PACKET_COUNT固定为1。
6. 运行时行为
该类内部维护 SWJ shadow pin 状态、当前 debug_port 和 transfer_abort 标志。
请求处理分三步:
- 主机通过 Interrupt OUT 发送 HID Output Report
- 设备在
OnDataOutComplete()中解析请求,把响应写入 IN 端点缓冲区 - IN 端点空闲时立即发送;正在发送时,响应留在双缓冲的另一半,上一次发送完成后发出
7. 使用示例
#include "daplink_v1.hpp"
extern LibXR::Debug::Swd& swd; // 平台提供的 SWD 后端
extern LibXR::GPIO& nreset; // 可选的 nRESET 引脚
using EPNumber = LibXR::USB::Endpoint::EPNumber;
LibXR::USB::DapLinkV1Class<LibXR::Debug::Swd> dap(EPNumber::EP1, EPNumber::EP1, swd,
&nreset);
LibXR::USB::DapLinkV1Class<LibXR::Debug::Swd>::InfoStrings info;
info.vendor = "XRobot";
info.product = "DAPLinkV1";
info.serial = "00000001";
info.firmware_ver = "1.0.0";
dap.SetInfoStrings(info);
// USB device class list: {{&dap}}
// usb_dev.Init(false);
// usb_dev.Start(false);
8. 与 DAPLinkV2 的区别
DapLinkV1Class:HID transport,PACKET_SIZE=64,PACKET_COUNT=1DapLinkV2Class:Bulk 传输,默认PACKET_SIZE=1024、PACKET_COUNT=4
如果主机工具链支持 CMSIS-DAP v2 Bulk,一般优先使用 DapLinkV2Class;
如果需要兼容仍依赖 HID 报告路径的主机,则使用 DapLinkV1Class。