samples: debug: add CMSIS DAP sample using USB as interface
Add CMSIS DAP sample using USB as interface. Signed-off-by: Maximilian Deubel <maximilian.deubel@nordicsemi.no> Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
This commit is contained in:
parent
9a9afb0b54
commit
94f48c7a78
7 changed files with 507 additions and 0 deletions
9
samples/subsys/dap/CMakeLists.txt
Normal file
9
samples/subsys/dap/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2023 Nordic Semiconductor ASA
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(dap)
|
||||||
|
|
||||||
|
FILE(GLOB app_sources src/*.c)
|
||||||
|
target_sources(app PRIVATE ${app_sources})
|
||||||
57
samples/subsys/dap/README.rst
Normal file
57
samples/subsys/dap/README.rst
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
.. _dap-sample:
|
||||||
|
|
||||||
|
DAP Sample Application
|
||||||
|
######################
|
||||||
|
|
||||||
|
Overview
|
||||||
|
********
|
||||||
|
|
||||||
|
This sample app demonstrates use of a SWDP interface driver and CMSIS DAP
|
||||||
|
controller through USB Bulk interface.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
************
|
||||||
|
|
||||||
|
This sample supports multiple hardware configurations:
|
||||||
|
|
||||||
|
The simplest configuration would be to connect `SWDIO` to `dio`, `SWDCLK` to `clk`
|
||||||
|
and optionally `nRESET` to `reset`. The optional `noe` pin is used to enable the port,
|
||||||
|
e.g. if the SWD connections are multiplexed.
|
||||||
|
|
||||||
|
Building and Running
|
||||||
|
********************
|
||||||
|
|
||||||
|
In order for our debug adapter to be recognized by pyOCD we need to change
|
||||||
|
Zephyr's VID/PID to IDs known to pyOCD, this is up to the user.
|
||||||
|
The following commands build and flash DAP sample.
|
||||||
|
|
||||||
|
.. zephyr-app-commands::
|
||||||
|
:zephyr-app: samples/subsys/dap
|
||||||
|
:board: nrf52840dk_nrf52840
|
||||||
|
:goals: flash
|
||||||
|
:compact:
|
||||||
|
|
||||||
|
Connect HIC to the target and try some pyOCD commands, for example:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
pyocd commander -t nrf52840
|
||||||
|
|
||||||
|
0029527 W Board ID FE5D is not recognized [mbed_board]
|
||||||
|
Connected to NRF52840 [Sleeping]: FE5D244DFE1F33DB
|
||||||
|
pyocd> read32 0x20004f18 32
|
||||||
|
20004f18: 20001160 2000244c 00000000 0000e407 | ..` .$L........|
|
||||||
|
20004f28: ffffffff ffffffff 00000000 aaaaaaaa |................|
|
||||||
|
pyocd> halt
|
||||||
|
Successfully halted device
|
||||||
|
pyocd> reg
|
||||||
|
general registers:
|
||||||
|
lr: 0x00009cdd r7: 0x00000000 (0)
|
||||||
|
pc: 0x000033ca r8: 0x00000000 (0)
|
||||||
|
r0: 0x00000000 (0) r9: 0x00000000 (0)
|
||||||
|
r1: 0x20002854 (536881236) r10: 0x00000000 (0)
|
||||||
|
r2: 0x20000be4 (536873956) r11: 0x00000000 (0)
|
||||||
|
r3: 0x00000000 (0) r12: 0x00000000 (0)
|
||||||
|
r4: 0x200017e8 (536877032) sp: 0x20002898
|
||||||
|
r5: 0x20001867 (536877159) xpsr: 0x61000000 (1627389952)
|
||||||
|
r6: 0x00000000 (0)
|
||||||
17
samples/subsys/dap/app.overlay
Normal file
17
samples/subsys/dap/app.overlay
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/ {
|
||||||
|
dp0 {
|
||||||
|
compatible = "zephyr,swdp-gpio";
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
clk-gpios = <&arduino_header 10 GPIO_ACTIVE_HIGH>; /* D4 */
|
||||||
|
noe-gpios = <&arduino_header 9 GPIO_ACTIVE_HIGH>; /* D3 */
|
||||||
|
dio-gpios = <&arduino_header 8 GPIO_PULL_UP>; /* D2 */
|
||||||
|
port-write-cycles = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
19
samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay
Normal file
19
samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/ {
|
||||||
|
dp0 {
|
||||||
|
compatible = "zephyr,swdp-gpio";
|
||||||
|
status = "okay";
|
||||||
|
clk-gpios = <&arduino_header 10 GPIO_ACTIVE_HIGH>; /* D4 */
|
||||||
|
dio-gpios = <&arduino_header 8 GPIO_PULL_UP>; /* D2 */
|
||||||
|
dout-gpios = <&arduino_header 9 GPIO_ACTIVE_HIGH>; /* D3 */
|
||||||
|
dnoe-gpios = <&arduino_header 12 GPIO_ACTIVE_HIGH>; /* D6 */
|
||||||
|
noe-gpios = <&arduino_header 11 GPIO_ACTIVE_HIGH>; /* D5 */
|
||||||
|
reset-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */
|
||||||
|
port-write-cycles = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
19
samples/subsys/dap/prj.conf
Normal file
19
samples/subsys/dap/prj.conf
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
CONFIG_STDOUT_CONSOLE=y
|
||||||
|
CONFIG_USB_DEVICE_STACK=y
|
||||||
|
CONFIG_USB_DEVICE_BOS=y
|
||||||
|
CONFIG_SERIAL=y
|
||||||
|
CONFIG_USB_DEVICE_PRODUCT="Zephyr CMSIS-DAP"
|
||||||
|
CONFIG_USB_DEVICE_PID=0x0204
|
||||||
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
CONFIG_UART_LINE_CTRL=y
|
||||||
|
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
|
||||||
|
|
||||||
|
CONFIG_LOG=y
|
||||||
|
|
||||||
|
CONFIG_USB_DRIVER_LOG_LEVEL_INF=y
|
||||||
|
CONFIG_USB_DEVICE_LOG_LEVEL_INF=y
|
||||||
|
CONFIG_DAP_LOG_LEVEL_INF=y
|
||||||
|
CONFIG_DP_DRIVER_LOG_LEVEL_INF=y
|
||||||
|
CONFIG_DAP=y
|
||||||
|
CONFIG_GPIO=y
|
||||||
|
CONFIG_NET_BUF=y
|
||||||
16
samples/subsys/dap/sample.yaml
Normal file
16
samples/subsys/dap/sample.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
sample:
|
||||||
|
name: DAP USB
|
||||||
|
tests:
|
||||||
|
sample.dap.bulk:
|
||||||
|
build_only: true
|
||||||
|
depends_on: arduino_gpio usb_device
|
||||||
|
platform_allow:
|
||||||
|
- nrf52840dk/nrf52840
|
||||||
|
- frdm_k64f
|
||||||
|
tags: dap
|
||||||
|
sample.dap.bulk.nrf:
|
||||||
|
build_only: true
|
||||||
|
depends_on: gpio usb_device
|
||||||
|
platform_allow:
|
||||||
|
- nrf52840dk/nrf52840
|
||||||
|
tags: dap
|
||||||
370
samples/subsys/dap/src/main.c
Normal file
370
samples/subsys/dap/src/main.c
Normal file
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/sys/byteorder.h>
|
||||||
|
#include <zephyr/usb/usb_device.h>
|
||||||
|
#include <zephyr/usb/bos.h>
|
||||||
|
#include <zephyr/usb/msos_desc.h>
|
||||||
|
#include <zephyr/net/buf.h>
|
||||||
|
|
||||||
|
#include <usb_descriptor.h>
|
||||||
|
#include <cmsis_dap.h>
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(dap_sample, LOG_LEVEL_INF);
|
||||||
|
|
||||||
|
NET_BUF_POOL_FIXED_DEFINE(dapusb_rx_pool, CONFIG_CMSIS_DAP_PACKET_COUNT,
|
||||||
|
CONFIG_CMSIS_DAP_PACKET_SIZE, 0, NULL);
|
||||||
|
|
||||||
|
static uint8_t rx_buf[CONFIG_CMSIS_DAP_PACKET_SIZE];
|
||||||
|
static uint8_t tx_buf[CONFIG_CMSIS_DAP_PACKET_SIZE];
|
||||||
|
|
||||||
|
static K_FIFO_DEFINE(dap_rx_queue);
|
||||||
|
|
||||||
|
#define DAP_IFACE_STR_DESC "CMSIS-DAP v2"
|
||||||
|
|
||||||
|
struct dap_iface_descriptor {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bString[USB_BSTRING_LENGTH(DAP_IFACE_STR_DESC)];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
USBD_STRING_DESCR_USER_DEFINE(primary) struct dap_iface_descriptor dap_iface_desc = {
|
||||||
|
.bLength = USB_STRING_DESCRIPTOR_LENGTH(DAP_IFACE_STR_DESC),
|
||||||
|
.bDescriptorType = USB_DESC_STRING,
|
||||||
|
.bString = DAP_IFACE_STR_DESC
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DAP_USB_EP_IN 0x81
|
||||||
|
#define DAP_USB_EP_OUT 0x01
|
||||||
|
#define DAP_USB_EP_IN_IDX 0
|
||||||
|
#define DAP_USB_EP_OUT_IDX 1
|
||||||
|
|
||||||
|
#define WEBUSB_VENDOR_CODE 0x21
|
||||||
|
#define WINUSB_VENDOR_CODE 0x20
|
||||||
|
|
||||||
|
/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */
|
||||||
|
#define CMSIS_DAP_V2_DEVICE_INTERFACE_GUID \
|
||||||
|
'{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, '3', 0x00, 'B', 0x00, \
|
||||||
|
'5', 0x00, 'A', 0x00, 'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, \
|
||||||
|
'3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, '6', 0x00, '6', 0x00, \
|
||||||
|
'3', 0x00, '-', 0x00, 'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, \
|
||||||
|
'-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, 'E', 0x00, '4', 0x00, \
|
||||||
|
'6', 0x00, '4', 0x00, '6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, \
|
||||||
|
'6', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
|
||||||
|
#define COMPATIBLE_ID_WINUSB \
|
||||||
|
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00
|
||||||
|
|
||||||
|
static struct msosv2_descriptor {
|
||||||
|
struct msosv2_descriptor_set_header header;
|
||||||
|
#if defined(CONFIG_USB_COMPOSITE_DEVICE)
|
||||||
|
struct msosv2_function_subset_header subset_header;
|
||||||
|
#endif
|
||||||
|
struct msosv2_compatible_id compatible_id;
|
||||||
|
struct msosv2_guids_property guids_property;
|
||||||
|
} __packed msosv2_cmsis_dap_desc = {
|
||||||
|
/*
|
||||||
|
* Microsoft OS 2.0 descriptor set. This tells Windows what kind
|
||||||
|
* of device this is and to install the WinUSB driver.
|
||||||
|
*/
|
||||||
|
.header = {
|
||||||
|
.wLength = sizeof(struct msosv2_descriptor_set_header),
|
||||||
|
.wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR,
|
||||||
|
.dwWindowsVersion = 0x06030000,
|
||||||
|
.wTotalLength = sizeof(struct msosv2_descriptor),
|
||||||
|
},
|
||||||
|
#if defined(CONFIG_USB_COMPOSITE_DEVICE)
|
||||||
|
.subset_header = {
|
||||||
|
.wLength = sizeof(struct msosv2_function_subset_header),
|
||||||
|
.wDescriptorType = MS_OS_20_SUBSET_HEADER_FUNCTION,
|
||||||
|
.wSubsetLength = sizeof(struct msosv2_function_subset_header)
|
||||||
|
+ sizeof(struct msosv2_compatible_id)
|
||||||
|
+ sizeof(struct msosv2_guids_property),
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
.compatible_id = {
|
||||||
|
.wLength = sizeof(struct msosv2_compatible_id),
|
||||||
|
.wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID,
|
||||||
|
.CompatibleID = {COMPATIBLE_ID_WINUSB},
|
||||||
|
},
|
||||||
|
.guids_property = {
|
||||||
|
.wLength = sizeof(struct msosv2_guids_property),
|
||||||
|
.wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY,
|
||||||
|
.wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ,
|
||||||
|
.wPropertyNameLength = 42,
|
||||||
|
.PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME},
|
||||||
|
.wPropertyDataLength = 80,
|
||||||
|
.bPropertyData = {CMSIS_DAP_V2_DEVICE_INTERFACE_GUID},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc {
|
||||||
|
struct usb_bos_platform_descriptor platform;
|
||||||
|
struct usb_bos_capability_msos cap;
|
||||||
|
} __packed bos_cap_msosv2 = {
|
||||||
|
/* Microsoft OS 2.0 Platform Capability Descriptor */
|
||||||
|
.platform = {
|
||||||
|
.bLength = sizeof(struct usb_bos_platform_descriptor)
|
||||||
|
+ sizeof(struct usb_bos_capability_msos),
|
||||||
|
.bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
|
||||||
|
.bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM,
|
||||||
|
.bReserved = 0,
|
||||||
|
.PlatformCapabilityUUID = {
|
||||||
|
/**
|
||||||
|
* MS OS 2.0 Platform Capability ID
|
||||||
|
* D8DD60DF-4589-4CC7-9CD2-659D9E648A9F
|
||||||
|
*/
|
||||||
|
0xDF, 0x60, 0xDD, 0xD8,
|
||||||
|
0x89, 0x45,
|
||||||
|
0xC7, 0x4C,
|
||||||
|
0x9C, 0xD2,
|
||||||
|
0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.cap = {
|
||||||
|
/* Windows version (8.1) (0x06030000) */
|
||||||
|
.dwWindowsVersion = sys_cpu_to_le32(0x06030000),
|
||||||
|
.wMSOSDescriptorSetTotalLength =
|
||||||
|
sys_cpu_to_le16(sizeof(msosv2_cmsis_dap_desc)),
|
||||||
|
.bMS_VendorCode = WINUSB_VENDOR_CODE,
|
||||||
|
.bAltEnumCode = 0x00
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc {
|
||||||
|
struct usb_bos_platform_descriptor platform;
|
||||||
|
struct usb_bos_capability_webusb cap;
|
||||||
|
} __packed bos_cap_webusb = {
|
||||||
|
/* WebUSB Platform Capability Descriptor:
|
||||||
|
* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
|
||||||
|
*/
|
||||||
|
.platform = {
|
||||||
|
.bLength = sizeof(struct usb_bos_platform_descriptor)
|
||||||
|
+ sizeof(struct usb_bos_capability_webusb),
|
||||||
|
.bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
|
||||||
|
.bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM,
|
||||||
|
.bReserved = 0,
|
||||||
|
/* WebUSB Platform Capability UUID
|
||||||
|
* 3408b638-09a9-47a0-8bfd-a0768815b665
|
||||||
|
*/
|
||||||
|
.PlatformCapabilityUUID = {
|
||||||
|
0x38, 0xB6, 0x08, 0x34,
|
||||||
|
0xA9, 0x09,
|
||||||
|
0xA0, 0x47,
|
||||||
|
0x8B, 0xFD,
|
||||||
|
0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.cap = {
|
||||||
|
.bcdVersion = sys_cpu_to_le16(0x0100),
|
||||||
|
.bVendorCode = WEBUSB_VENDOR_CODE,
|
||||||
|
.iLandingPage = 0x01
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* URL Descriptor: https://wicg.github.io/webusb/#url-descriptor */
|
||||||
|
static const uint8_t webusb_origin_url[] = {
|
||||||
|
/* Length, DescriptorType, Scheme */
|
||||||
|
24, 0x03, 0x01,
|
||||||
|
'w', 'w', 'w', '.',
|
||||||
|
'z', 'e', 'p', 'h', 'y', 'r', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.',
|
||||||
|
'o', 'r', 'g', '/',
|
||||||
|
};
|
||||||
|
|
||||||
|
static int msosv2_vendor_handle_req(struct usb_setup_packet *setup,
|
||||||
|
int32_t *len, uint8_t **data)
|
||||||
|
{
|
||||||
|
if (usb_reqtype_is_to_device(setup)) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setup->bRequest == WEBUSB_VENDOR_CODE && setup->wIndex == 0x02) {
|
||||||
|
*data = (uint8_t *)(&webusb_origin_url);
|
||||||
|
*len = sizeof(webusb_origin_url);
|
||||||
|
|
||||||
|
LOG_DBG("Get URL request");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setup->bRequest == WINUSB_VENDOR_CODE &&
|
||||||
|
setup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) {
|
||||||
|
*data = (uint8_t *)(&msosv2_cmsis_dap_desc);
|
||||||
|
*len = sizeof(msosv2_cmsis_dap_desc);
|
||||||
|
|
||||||
|
LOG_DBG("Get MS OS Descriptors v2");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBD_CLASS_DESCR_DEFINE(primary, 0) struct {
|
||||||
|
struct usb_if_descriptor if0;
|
||||||
|
struct usb_ep_descriptor if0_out_ep;
|
||||||
|
struct usb_ep_descriptor if0_in_ep;
|
||||||
|
} __packed dapusb_desc = {
|
||||||
|
.if0 = {
|
||||||
|
.bLength = sizeof(struct usb_if_descriptor),
|
||||||
|
.bDescriptorType = USB_DESC_INTERFACE,
|
||||||
|
.bInterfaceNumber = 0,
|
||||||
|
.bAlternateSetting = 0,
|
||||||
|
.bNumEndpoints = 2,
|
||||||
|
.bInterfaceClass = USB_BCC_VENDOR,
|
||||||
|
.bInterfaceSubClass = 0,
|
||||||
|
.bInterfaceProtocol = 0,
|
||||||
|
.iInterface = 0,
|
||||||
|
},
|
||||||
|
.if0_out_ep = {
|
||||||
|
.bLength = sizeof(struct usb_ep_descriptor),
|
||||||
|
.bDescriptorType = USB_DESC_ENDPOINT,
|
||||||
|
.bEndpointAddress = DAP_USB_EP_OUT,
|
||||||
|
.bmAttributes = USB_DC_EP_BULK,
|
||||||
|
.wMaxPacketSize = sys_cpu_to_le16(CONFIG_CMSIS_DAP_PACKET_SIZE),
|
||||||
|
.bInterval = 0,
|
||||||
|
},
|
||||||
|
.if0_in_ep = {
|
||||||
|
.bLength = sizeof(struct usb_ep_descriptor),
|
||||||
|
.bDescriptorType = USB_DESC_ENDPOINT,
|
||||||
|
.bEndpointAddress = DAP_USB_EP_IN,
|
||||||
|
.bmAttributes = USB_DC_EP_BULK,
|
||||||
|
.wMaxPacketSize = sys_cpu_to_le16(CONFIG_CMSIS_DAP_PACKET_SIZE),
|
||||||
|
.bInterval = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_ep_cfg_data dapusb_ep_data[] = {
|
||||||
|
{
|
||||||
|
.ep_cb = usb_transfer_ep_callback,
|
||||||
|
.ep_addr = DAP_USB_EP_OUT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ep_cb = usb_transfer_ep_callback,
|
||||||
|
.ep_addr = DAP_USB_EP_IN
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void iface_string_desc_init(struct usb_cfg_data *bulk_cfg)
|
||||||
|
{
|
||||||
|
struct usb_if_descriptor *bulk_if = bulk_cfg->interface_descriptor;
|
||||||
|
|
||||||
|
bulk_if->iInterface = usb_get_str_descriptor_idx(&dap_iface_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dapusb_read_cb(uint8_t ep, int size, void *priv)
|
||||||
|
{
|
||||||
|
struct usb_cfg_data *cfg = priv;
|
||||||
|
struct net_buf *buf;
|
||||||
|
|
||||||
|
LOG_DBG("cfg %p ep %x size %u", cfg, ep, size);
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
goto read_cb_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = net_buf_alloc(&dapusb_rx_pool, K_FOREVER);
|
||||||
|
net_buf_add_mem(buf, rx_buf, MIN(size, CONFIG_CMSIS_DAP_PACKET_SIZE));
|
||||||
|
k_fifo_put(&dap_rx_queue, buf);
|
||||||
|
|
||||||
|
read_cb_done:
|
||||||
|
usb_transfer(ep, rx_buf, sizeof(rx_buf), USB_TRANS_READ, dapusb_read_cb, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dapusb_dev_status_cb(struct usb_cfg_data *cfg,
|
||||||
|
enum usb_dc_status_code status,
|
||||||
|
const uint8_t *param)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(param);
|
||||||
|
|
||||||
|
if (status == USB_DC_CONFIGURED) {
|
||||||
|
dapusb_read_cb(cfg->endpoint[DAP_USB_EP_IN_IDX].ep_addr, 0, cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dapusb_interface_config(struct usb_desc_header *head,
|
||||||
|
uint8_t bInterfaceNumber)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(head);
|
||||||
|
|
||||||
|
dapusb_desc.if0.bInterfaceNumber = bInterfaceNumber;
|
||||||
|
#if defined(CONFIG_USB_COMPOSITE_DEVICE)
|
||||||
|
msosv2_cmsis_dap_desc.subset_header.bFirstInterface = bInterfaceNumber;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
USBD_DEFINE_CFG_DATA(dapusb_config) = {
|
||||||
|
.usb_device_description = NULL,
|
||||||
|
.interface_config = dapusb_interface_config,
|
||||||
|
.interface_descriptor = &dapusb_desc.if0,
|
||||||
|
.cb_usb_status = dapusb_dev_status_cb,
|
||||||
|
.interface = {
|
||||||
|
.class_handler = NULL,
|
||||||
|
.custom_handler = NULL,
|
||||||
|
.vendor_handler = msosv2_vendor_handle_req,
|
||||||
|
},
|
||||||
|
.num_endpoints = ARRAY_SIZE(dapusb_ep_data),
|
||||||
|
.endpoint = dapusb_ep_data
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dap_usb_process(void)
|
||||||
|
{
|
||||||
|
uint8_t ep = dapusb_config.endpoint[DAP_USB_EP_OUT_IDX].ep_addr;
|
||||||
|
struct net_buf *buf;
|
||||||
|
size_t len;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
buf = k_fifo_get(&dap_rx_queue, K_FOREVER);
|
||||||
|
|
||||||
|
len = dap_execute_cmd(buf->data, tx_buf);
|
||||||
|
LOG_DBG("response length %u, starting with [0x%02X, 0x%02X]",
|
||||||
|
len, tx_buf[0], tx_buf[1]);
|
||||||
|
net_buf_unref(buf);
|
||||||
|
|
||||||
|
err = usb_transfer_sync(ep, tx_buf, len, USB_TRANS_WRITE | USB_TRANS_NO_ZLP);
|
||||||
|
if (err < 0 || err != len) {
|
||||||
|
LOG_ERR("usb_transfer_sync failed, %d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
const struct device *const swd_dev = DEVICE_DT_GET_ONE(zephyr_swdp_gpio);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!device_is_ready(swd_dev)) {
|
||||||
|
LOG_ERR("SWD device is not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dap_setup(swd_dev);
|
||||||
|
if (ret) {
|
||||||
|
LOG_ERR("Failed to initialize DAP controller, %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add MS OS 2.0 BOS descriptor to BOS structure */
|
||||||
|
usb_bos_register_cap((void *)&bos_cap_msosv2);
|
||||||
|
/* Point interface index to string descriptor */
|
||||||
|
iface_string_desc_init(&dapusb_config);
|
||||||
|
|
||||||
|
ret = usb_enable(NULL);
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG_ERR("Failed to enable USB");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!dap_usb_process()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return usb_disable();
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue