commit 23d950c8e902562a5194fc9b7e2fa44b3bf4e1eb
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 26 Feb 2023 19:48:59 -0800
initial checkin
Diffstat:
A | .gitignore | | | 2 | ++ |
A | Makefile | | | 13 | +++++++++++++ |
A | README.md | | | 6 | ++++++ |
A | src/arm-debug.h | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/cmsis-dap-protocol.h | | | 132 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/usb.c | | | 124 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/usb.h | | | 20 | ++++++++++++++++++++ |
A | src/xdebug.c | | | 249 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
8 files changed, 603 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,2 @@
+.*.swp
+bin/
diff --git a/Makefile b/Makefile
@@ -0,0 +1,13 @@
+
+all: bin/xdebug
+
+SRCS := src/xdebug.c src/usb.c
+DEPS := src/arm-debug.h src/cmsis-dap-protocol.h src/usb.h
+
+bin/xdebug: $(SRCS) $(DEPS)
+ @mkdir -p $(dir $@)
+ gcc -o $@ -Wall -g -O1 $(SRCS) -lusb-1.0
+
+clean:
+ rm -f bin/
+
diff --git a/README.md b/README.md
@@ -0,0 +1,6 @@
+# xdebug
+
+Rewriting mdebug to reflect ARM ADI v5.2, newer hardware,
+tidier code, and focused on CMSIS-DAP instead of my own
+RSWD protocol (so it will work with a wider variety of
+hardware debug probes).
diff --git a/src/arm-debug.h b/src/arm-debug.h
@@ -0,0 +1,57 @@
+// Copyright 2023, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#pragma once
+
+// high nybble is banksel
+#define DP_DPIDR 0x00 // RO Debug Port ID
+#define DP_ABORT 0x00 // WO
+#define DP_CS 0x04 // RW CTRL/STAT
+#define DP_DLCR 0x14 // RW Data Link Control
+#define DP_TARGETID 0x24 // RO v2
+#define DP_DLPIDR 0x34 // RO v2 Data Link ID
+#define DP_EVENTSTAT 0x44 // RO v2
+#define DP_SELECT 0x08 // WO
+#define DP_RESEND 0x08 // RO v2 Return last AP or RDBUFF read data
+#define DP_RDBUFF 0x0C // RO
+#define DP_TARGETSEL 0x0C // WO v2
+
+#define DP_ABORT_DAPABORT 0x01U // Abort Current AP Txn
+#define DP_ABORT_STKCMPCLR 0x02U // clear CS.STICKYCMP
+#define DP_ABORT_STKERRCLR 0x04U // clear CS.STICKYERR
+#define DP_ABORT_WDERRCLR 0x08U // clear CS.WDATAERR
+#define DP_ABORT_ORUNERRCLR 0x10U // clear CS.STICKYORUN
+
+#define DP_CS_ORUNDETECT 0x00000001U // RW
+#define DP_CS_STICKYORUN 0x00000002U // RO/WI
+#define DP_CS_MODE_MASK 0x0000000CU // RW
+#define DP_CS_MODE_NORMAL 0x00000000U
+#define DP_CS_MODE_PUSHED_VERIFY 0x00000004U
+#define DP_CS_MODE_PUSHED_COMPARE 0x00000008U
+#define DP_CS_MODE_RESERVED 0x0000000CU
+#define DP_CS_STICKYCMP 0x00000010U // RO/WI for pushed ops
+#define DP_CS_STICKYERR 0x00000020U // RO/WI error occurred in AP txn
+#define DP_CS_READOK 0x00000040U // RO/WI last AP or RDBUFF RD was OK
+#define DP_CS_WDATAERR 0x00000080U // RO/WI
+#define DP_CS_MASKLANE(n) (((n) & 0xF) << 8) // RW
+#define DP_CS_TRNCNT(n) (((n) & 0xFFF) << 12)
+#define DP_CS_CDBGRSTREQ 0x04000000U // RW or RAZ/WI
+#define DP_CS_CDBGRSTACK 0x08000000U // RO
+#define DP_CS_CDBGPWRUPREQ 0x10000000U // RW
+#define DP_CS_CDBGPWRUPACK 0x20000000U // RO
+#define DP_CS_CSYSPWRUPREQ 0x40000000U // RW
+#define DP_CS_CSYSPWRUPACK 0x80000000U // RO
+
+#define DP_DLCR_TURNROUND_MASK 0x00000300U
+#define DP_DLCR_TURNROUND_1 0x00000000U
+#define DP_DLCR_TURNROUND_2 0x00000100U
+#define DP_DLCR_TURNROUND_3 0x00000200U
+#define DP_DLCR_TURNROUND_4 0x00000300U
+#define DP_DLCR_MUST_BE_ONE 0x00000040U
+
+#define DP_EVENTSTAT_EA 0x000000001U
+
+#define DP_SELECT_DPBANK(n) ((n) & 0xF)
+#define DP_SELECT_APBANK(n) (((n) & 0xF) << 4)
+#define DP_SELECT_AP(n) (((n) & 0xFF) << 24)
+
diff --git a/src/cmsis-dap-protocol.h b/src/cmsis-dap-protocol.h
@@ -0,0 +1,132 @@
+// Copyright 2023, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#pragma once
+
+#define DAP_Info 0x00 // BYTE(DI_*)
+// Response LEN BYTES[LEN]
+
+#define DI_Vendor_Name 0x01
+#define DI_Product_Name 0x02
+#define DI_Serial_Number 0x03
+#define DI_Protocol_Version 0x04
+#define DI_Target_Device_Vendor 0x05
+#define DI_Target_Device_Name 0x06
+#define DI_Target_Board_Vendor 0x07
+#define DI_Target_Board_Name 0x08
+#define DI_Product_Firmware_Version 0x09
+#define DI_Capabilities 0xF0 // BYTE
+#define DI_Test_Domain_Timer 0xF1 // DWORD
+#define DI_UART_RX_Buffer_Size 0xFB // WORD
+#define DI_UART_TX_Buffer_Size 0xFC // WORD
+#define DI_SWO_Trace_Buffer_Size 0xFD // WORD
+#define DI_Max_Packet_Count 0xFE // BYTE
+#define DI_Max_Packet_Size 0xFF // SHORT
+
+// Capabilities Reply 0x00 LEN I0 I1
+#define I0_SWD 0x01
+#define I0_JTAG 0x02
+#define I0_SWO_UART 0x04
+#define I0_SWO_Manchester 0x08
+#define I0_Atomic_Commands 0x10
+#define I0_Test_Domain_Timer 0x20
+#define I0_SWO_Streaming_Trace 0x40
+#define I0_UART_Comm_Port 0x80
+
+#define I1_USB_COM_Port 0x01
+
+
+#define DAP_HostStatus 0x01 // BYTE(Type) BYTE(ZeroOffOneOn)
+// set host status LEDs
+#define HS_Type_Connected 0
+#define HS_Type_Running 1
+
+#define DAP_Connect 0x02 // BYTE(Port)
+// Reponse BYTE(Port)
+
+#define PORT_DEFAULT 0
+#define PORT_SWD 1
+#define PORT_JTAG 2
+
+#define DAP_Disconnect 0x03
+
+#define DAP_WriteABORT 0x08 // BYTE(Index) WORD(value)
+// Write an abort request to the target
+
+#define DAP_Delay 0x09 // SHORT(DelayMicros)
+
+#define DAP_ResetTarget 0x0A
+// Response BYTE(Status) BYTE(Execute)
+// Execute 1 = device specific reset sequence implemented
+
+#define DAP_SWJ_Pins 0x10 // BYTE(PinOut) BYTE(PinSel) WORD(PinWaitMicros)
+// Response BYTE(PinInput)
+// Modify pins (PinOut) where selected (PinSel)
+
+#define PIN_SWCLK 0x01
+#define PIN_TCK 0x01
+#define PIN_SWDIO 0x02
+#define PIN_TMS 0x02
+#define PIN_TDI 0x04
+#define PIN_TDO 0x08
+#define PIN_nTRST 0x20
+#define PIN_nRESET 0x80
+
+#define DAP_SWD_Configure 0x13 // BYTE(Config)
+#define CFG_Turnaround_1 0x00
+#define CFG_Turnaround_2 0x01
+#define CFG_Turnaround_3 0x02
+#define CFG_Turnaround_4 0x03
+#define CFG_AlwaysDataPhase 0x04
+
+#define DAP_SWD_Sequence 0x1D
+// First Byte is Count
+// Then one Info byte (and, if output, data) per Count
+// Data is LSB first, padded to byte boundary
+#define SEQ_OUTPUT 0x00
+#define SEQ_INPUT 0x80
+// Response: BYTE(STATUS) DATA (LSB first)
+
+
+#define DAP_TransferConfigure 0x04
+// BYTE(IdleCycles) SHORT(WaitRetry) SHORT(MatchRetry)
+// idle cycles - number of extra idle cycles after each transfer
+// wait retry - max number of retries after WAIT response
+// match retry - max number of retries on reads w/ value match
+
+#define DAP_Transfer 0x05
+// BYTE(Index) BYTE(Count) followed by Count instances of
+// BYTE(XferReq) WORD(Value) WORD(MatchMask) WORD(ValueMatch)
+#define XFER_DebugPort 0x00
+#define XFER_AccessPort 0x01
+#define XFER_Write 0x00
+#define XFER_Read 0x02
+#define XFER_Addr_00 0x00
+#define XFER_Addr_04 0x04
+#define XFER_Addr_08 0x08
+#define XFER_Addr_0C 0x0C
+#define XFER_ValueMatch 0x10
+#define XFER_MatchMask 0x20
+#define XFER_TimeStamp 0x80
+
+#define RSP_ACK_MASK 0x07
+#define RSP_ACK_OK 0x01
+#define RSP_ACK_WAIT 0x02
+#define RSP_ACK_FAULT 0x04
+#define RSP_ProtocolError 0x08
+#define RSP_ValueMismatch 0x10
+// Reponse BYTE(Count) BYTE(Response) WORD(TimeStamp)? WORD(Data)*
+
+#define DAP_TransferBlock 0x06
+// BYTE(Index) SHORT(Count) BYTE(XferReq) WORD(Data)*
+// XFER as above but not ValueMatch/MatchMask/TimeStamp
+// Response SHORT(Count) BYTE(Response) WORD(Data)*
+
+#define DAP_ExecuteCommands 0x7F
+// BYTE(Count) Count x Commands
+// Response BYTE(Count) Count x Responses
+
+#define DAP_QueueCommands 0x7E
+// as above but N packets can be sent
+// first non-queue-commands packet triggers execution
+
diff --git a/src/usb.c b/src/usb.c
@@ -0,0 +1,124 @@
+// Copyright 2014, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <libusb-1.0/libusb.h>
+
+#include "usb.h"
+
+struct usb_handle {
+ libusb_device_handle *dev;
+ unsigned ei;
+ unsigned eo;
+};
+
+static libusb_context *usb_ctx = NULL;
+
+usb_handle *usb_open(unsigned vid, unsigned pid, unsigned ifc) {
+ usb_handle *usb;
+ int r;
+
+ if (usb_ctx == NULL) {
+ if (libusb_init(&usb_ctx) < 0) {
+ usb_ctx = NULL;
+ return NULL;
+ }
+ }
+
+ usb = malloc(sizeof(usb_handle));
+ if (usb == 0) {
+ return NULL;
+ }
+
+ /* TODO: extract from descriptors */
+ switch (ifc) {
+ case 0:
+ usb->ei = 0x81;
+ usb->eo = 0x01;
+ break;
+ case 1:
+ usb->ei = 0x82;
+ usb->eo = 0x02;
+ break;
+ case 42:
+ usb->ei = 0x85;
+ usb->eo = 0x04;
+ ifc = 0;
+ break;
+ default:
+ goto fail;
+ }
+
+ usb->dev = libusb_open_device_with_vid_pid(usb_ctx, vid, pid);
+ if (usb->dev == NULL) {
+ goto fail;
+ }
+ // This causes problems on re-attach. Maybe need for OSX?
+ // On Linux it's completely happy without us explicitly setting a configuration.
+ //r = libusb_set_configuration(usb->dev, 1);
+ r = libusb_claim_interface(usb->dev, ifc);
+ if (r < 0) {
+ fprintf(stderr, "failed to claim interface #%d\n", ifc);
+ goto close_fail;
+ }
+
+#ifdef __APPLE__
+ // make sure everyone's data toggles agree
+ // makes things worse on Linux, but happy on OSX
+ libusb_clear_halt(usb->dev, usb->ei);
+ libusb_clear_halt(usb->dev, usb->eo);
+#endif
+
+ return usb;
+
+close_fail:
+ libusb_close(usb->dev);
+fail:
+ free(usb);
+ return NULL;
+}
+
+void usb_close(usb_handle *usb) {
+ libusb_close(usb->dev);
+ free(usb);
+}
+
+int usb_ctrl(usb_handle *usb, void *data,
+ uint8_t typ, uint8_t req, uint16_t val, uint16_t idx, uint16_t len) {
+ int r = libusb_control_transfer(usb->dev, typ, req, val, idx, data, len, 5000);
+ if (r < 0) {
+ return -1;
+ } else {
+ return r;
+ }
+}
+
+int usb_read(usb_handle *usb, void *data, int len) {
+ int xfer = len;
+ int r = libusb_bulk_transfer(usb->dev, usb->ei, data, len, &xfer, 5000);
+ if (r < 0) {
+ return -1;
+ }
+ return xfer;
+}
+
+int usb_read_forever(usb_handle *usb, void *data, int len) {
+ int xfer = len;
+ int r = libusb_bulk_transfer(usb->dev, usb->ei, data, len, &xfer, 0);
+ if (r < 0) {
+ return -1;
+ }
+ return xfer;
+}
+
+int usb_write(usb_handle *usb, const void *data, int len) {
+ int xfer = len;
+ int r = libusb_bulk_transfer(usb->dev, usb->eo, (void*) data, len, &xfer, 5000);
+ if (r < 0) {
+ return -1;
+ }
+ return xfer;
+}
+
diff --git a/src/usb.h b/src/usb.h
@@ -0,0 +1,20 @@
+// Copyright 2014, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#ifndef _USB_H_
+#define _USB_H_
+
+#include <stdint.h>
+
+typedef struct usb_handle usb_handle;
+
+/* simple usb api for devices with bulk in+out interfaces */
+
+usb_handle *usb_open(unsigned vid, unsigned pid, unsigned ifc);
+void usb_close(usb_handle *usb);
+int usb_read(usb_handle *usb, void *data, int len);
+int usb_read_forever(usb_handle *usb, void *data, int len);
+int usb_write(usb_handle *usb, const void *data, int len);
+int usb_ctrl(usb_handle *usb, void *data,
+ uint8_t typ, uint8_t req, uint16_t val, uint16_t idx, uint16_t len);
+#endif
diff --git a/src/xdebug.c b/src/xdebug.c
@@ -0,0 +1,249 @@
+// Copyright 2023, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "usb.h"
+#include "cmsis-dap-protocol.h"
+
+struct debug_context {
+ usb_handle* usb;
+ unsigned connected;
+
+ // last dp select written
+ uint32_t dp_select;
+
+ uint32_t max_packet_count;
+ uint32_t max_packet_size;
+};
+
+
+typedef struct debug_context DC;
+
+
+int dap_get_info(DC* dc, unsigned di, void *out, unsigned minlen, unsigned maxlen) {
+ uint8_t buf[256 + 2];
+ buf[0] = DAP_Info;
+ buf[1] = di;
+ if (usb_write(dc->usb, buf, 2) != 2) {
+ return -1;
+ }
+ int sz = usb_read(dc->usb, buf, 256 + 2);
+ if ((sz < 2) || (buf[0] != DAP_Info)) {
+ return -1;
+ }
+ //printf("0x%02x > 0x%02x 0x%02x\n", di, buf[0], buf[1]);
+ if ((buf[1] < minlen) || (buf[1] > maxlen)) {
+ return -1;
+ }
+ memcpy(out, buf + 2, buf[1]);
+ return buf[1];
+}
+
+void dump(const char* str, const void* ptr, unsigned len) {
+ const uint8_t* x = ptr;
+ fprintf(stderr, "%s", str);
+ while (len > 0) {
+ fprintf(stderr, " %02x", *x++);
+ len--;
+ }
+ fprintf(stderr, "\n");
+}
+
+int dap_cmd(DC* dc, const void* tx, unsigned txlen, void* rx, unsigned rxlen) {
+ uint8_t cmd = ((const uint8_t*) tx)[0];
+ dump("TX>", tx, txlen);
+ if (usb_write(dc->usb, tx, txlen) != txlen) {
+ fprintf(stderr, "dap_cmd(0x%02x): usb write error\n", cmd);
+ return -1;
+ }
+ int sz = usb_read(dc->usb, rx, rxlen);
+ if (sz < 1) {
+ fprintf(stderr, "dap_cmd(0x%02x): usb read error\n", cmd);
+ return -1;
+ }
+ dump("RX>", rx, rxlen);
+ if (((uint8_t*) rx)[0] != cmd) {
+ fprintf(stderr, "dap_cmd(0x%02x): unsupported (0x%02x)\n",
+ cmd, ((uint8_t*) rx)[0]);
+ return -1;
+ }
+ fprintf(stderr, "dap_cmd(0x%02x): sz %u\n", cmd, sz);
+ return sz;
+}
+
+int dap_cmd_std(DC* dc, const char* name, uint8_t* io,
+ unsigned txlen, unsigned rxlen) {
+ if (dap_cmd(dc, io, txlen, io, rxlen) < 0) {
+ return -1;
+ }
+ if (io[1] != 0) {
+ fprintf(stderr, "%s status 0x%02x\n", name, io[1]);
+ return -1;
+ }
+ return 0;
+}
+
+int dap_connect(DC* dc) {
+ uint8_t io[2] = { DAP_Connect, PORT_SWD };
+ return dap_cmd_std(dc, "dap_connect()", io, 2, 2);
+}
+
+int dap_swd_configure(DC* dc, unsigned cfg) {
+ uint8_t io[2] = { DAP_SWD_Configure, cfg };
+ return dap_cmd_std(dc, "dap_swd_configure()", io, 2, 2);
+}
+
+int dap_transfer_configure(DC* dc, unsigned idle, unsigned wait, unsigned match) {
+ uint8_t io[6] = { DAP_TransferConfigure, idle, wait, wait >> 8, match, match >> 8};
+ return dap_cmd_std(dc, "dap_transfer_configure()", io, 6, 2);
+}
+
+int dap_xfer_wr1(DC* dc, unsigned cfg, uint32_t val) {
+ uint8_t io[8] = {
+ DAP_Transfer, 0, 1, cfg & 0x0D,
+ val, val >> 8, val >> 16, val >> 24 };
+ if (dap_cmd(dc, io, 8, io, 3) < 0) {
+ return -1;
+ }
+ if (io[1] != 0) {
+ fprintf(stderr, "dap_xfer_wr1() invalid count %u\n", io[1]);
+ return -1;
+ }
+ if (io[2] == RSP_ACK_OK) {
+ return 0;
+ }
+ fprintf(stderr, "dap_xfer_wr1() status 0x%02x\n", io[2]);
+ return -1;
+}
+
+int dap_xfer_rd1(DC* dc, unsigned cfg, uint32_t* val) {
+ uint8_t io[8] = {
+ DAP_Transfer, 0, 1, XFER_Read | (cfg & 0x0D) };
+ if (dap_cmd(dc, io, 4, io, 7) < 0) {
+ return -1;
+ }
+ if (io[1] != 1) {
+ fprintf(stderr, "dap_xfer_rd1() invalid count %u\n", io[1]);
+ return -1;
+ }
+ if (io[2] == RSP_ACK_OK) {
+ memcpy(val, io + 3, 4);
+ return 0;
+ }
+ fprintf(stderr, "dap_xfer_rd1() status 0x%02x\n", io[2]);
+ return -1;
+}
+
+int swd_init(DC* dc) {
+ uint8_t io[23] = {
+ DAP_SWD_Sequence, 3,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 64 1s
+ 0x10, 0x9E, 0xE7, // JTAG to SWD magic sequence
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, // 60 1s, 4 0s
+ };
+ if (dap_cmd(dc, io, 23, io, 2) < 0) {
+ return -1;
+ }
+ if (io[1] != 0) {
+ fprintf(stderr, "swd_init() failure 0x%02x\n", io[1]);
+ return -1;
+ }
+ return 0;
+}
+
+int dc_init(DC* dc, usb_handle* usb) {
+ uint8_t buf[256 + 2];
+ uint32_t n32;
+ uint16_t n16;
+ uint8_t n8;
+
+ memset(dc, 0, sizeof(DC));
+ dc->usb = usb;
+ dc->max_packet_count = 1;
+ dc->max_packet_size = 64;
+
+ buf[0] = DAP_Info;
+ for (unsigned n = 0; n < 10; n++) {
+ int sz = dap_get_info(dc, n, buf, 0, 255);
+ if (sz > 0) {
+ buf[sz] = 0;
+ printf("0x%02x: '%s'\n", n, (char*) buf);
+ }
+ }
+
+ buf[0] = 0; buf[1] = 0;
+ if (dap_get_info(dc, DI_Capabilities, buf, 1, 2) > 0) {
+ printf("Capabilities: 0x%02x 0x%02x\n", buf[0], buf[1]);
+ printf("Capabilities:");
+ if (buf[0] & I0_SWD) printf(" SWD");
+ if (buf[0] & I0_JTAG) printf(" JTAG");
+ if (buf[0] & I0_SWO_UART) printf(" SWO(UART)");
+ if (buf[0] & I0_SWO_Manchester) printf(" SWO(Manchester)");
+ if (buf[0] & I0_Atomic_Commands) printf(" ATOMIC");
+ if (buf[0] & I0_Test_Domain_Timer) printf(" TIMER");
+ if (buf[0] & I0_SWO_Streaming_Trace) printf(" SWO(Streaming)");
+ if (buf[0] & I0_UART_Comm_Port) printf(" UART");
+ if (buf[1] & I1_USB_COM_Port) printf(" USBCOM");
+ printf("\n");
+ }
+ if (dap_get_info(dc, DI_UART_RX_Buffer_Size, &n32, 4, 4) == 4) {
+ printf("UART RX Buffer Size: %u\n", n32);
+ }
+ if (dap_get_info(dc, DI_UART_TX_Buffer_Size, &n32, 4, 4) == 4) {
+ printf("UART TX Buffer Size: %u\n", n32);
+ }
+ if (dap_get_info(dc, DI_SWO_Trace_Buffer_Size, &n32, 4, 4) == 4) {
+ printf("SWO Trace Buffer Size: %u\n", n32);
+ }
+ if (dap_get_info(dc, DI_Max_Packet_Count, &n8, 1, 1) == 1) {
+ printf("Max Packet Count: %u\n", n8);
+ dc->max_packet_count = n8;
+ }
+ if (dap_get_info(dc, DI_Max_Packet_Size, &n16, 2, 2) == 2) {
+ printf("Max Packet Size: %u\n", n16);
+ dc->max_packet_size = n16;
+ }
+
+ if ((dc->max_packet_count < 1) || (dc->max_packet_size < 64)) {
+ fprintf(stderr, "dc_init() impossible packet configuration\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ usb_handle *usb;
+ uint32_t n;
+
+ usb = usb_open(0x1fc9, 0x0143, 0);
+ if (usb == 0) {
+ usb = usb_open(0x2e8a, 0x000c, 42);
+ if (usb == 0) {
+ fprintf(stderr, "cannot find device\n");
+ return -1;
+ }
+ }
+
+ DC context;
+ DC* dc = &context;
+ dc_init(dc, usb);
+
+ dap_connect(dc);
+ dap_swd_configure(dc, CFG_Turnaround_1);
+ dap_transfer_configure(dc, 8, 64, 0);
+ //dap_xfer_wr1(dc, XFER_DebugPort | XFER_Addr_04, 0x11553311);
+ swd_init(dc);
+ n = 0;
+ dap_xfer_rd1(dc, XFER_DebugPort, &n);
+ printf("IDCODE %08x\n", n);
+
+ return 0;
+}
+
+
+