http://www.keil.com/support/man/docs/dapdebug/dapdebug_introduction.htm

CMSIS-DAP is the interface firmware for a Debug Unit that connects the Debug Port to USB.

Debuggers, which execute on a host computer, connect via USB to the Debug Unit

and to the Device that runs the application software.

The Debug Unit connects via JTAG or SW to the target Device.

ARM Cortex processors provide the CoreSight Debug and Trace Unit.

CMSIS-DAP supports target devices that contain one or more Cortex processors.

The Debug Unit can be an integral part of the evaluation board or an external debug adapter.

https://mbed.org/handbook/CMSIS-DAP

The mbed HDK and mbed-enabled hardware support the CMSIS-DAP debug interface, which consists of an abstraction of the Cortex Debug Access Port (DAP) command set over a driver-less USB HID connection. This provides a USB connection to the DAP that major tool vendors have started to support. It even provides the flexibility for users to write their own debugger, or debug script using the USB bindings in languages like Python.

CMSIS-DAP provides a standardized way to access the Coresight Debug Access Port (DAP) of an ARM Cortex microcontroller via USB. CMSIS-DAP is generally implemented as an on-board interface chip, providing direct USB connection from a development board to a debugger running on a host computer on one side, and over JTAG (Joint Test Action Group) or SWD (Serial Wire Debug) to the target device to access the Coresight DAP on the other.

You can access the documentation on the ARM website. You will need to register for an ARM silver account to access the documentation.

There are several reasons concerning the introduction of CMSIS-DAP:

  • Before the CMSIS-DAP standard, a lot of USB wigglers implemented their own protocols. With this configuration, the host debugger has to be aware of these different protocols and has to implement all of them, which produces a lot of fragmentation and re-inventing the wheel. At the same time, the protocols were usually defined at the JTAG level, meaning they are slow. CMSIS-DAP provides a standardised interface for debuggers that is defined at the Coresight DAP level, allowing for a standard interface and fast driverless implementations.
  • With the new CMSIS-DAP layer, the host debugger can debug targets over SWD or JTAG without the need to implement these two protocols
  • The USB connection uses the HID driver class. As HID drivers are built-in in every Operating Systems, there is no need for a specific driver to be installed on the host computer
/******************************************************************************
* @file DAP.h
* @brief CMSIS-DAP Definitions
* @version V1.00
* @date 31. May 2012
*
* @note
* Copyright (C) 2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/ #ifndef __DAP_H__
#define __DAP_H__ // DAP Command IDs
#define ID_DAP_Info 0x00
#define ID_DAP_LED 0x01
#define ID_DAP_Connect 0x02
#define ID_DAP_Disconnect 0x03
#define ID_DAP_TransferConfigure 0x04
#define ID_DAP_Transfer 0x05
#define ID_DAP_TransferBlock 0x06
#define ID_DAP_TransferAbort 0x07
#define ID_DAP_WriteABORT 0x08
#define ID_DAP_Delay 0x09
#define ID_DAP_ResetTarget 0x0A
#define ID_DAP_SWJ_Pins 0x10
#define ID_DAP_SWJ_Clock 0x11
#define ID_DAP_SWJ_Sequence 0x12
#define ID_DAP_SWD_Configure 0x13
#define ID_DAP_JTAG_Sequence 0x14
#define ID_DAP_JTAG_Configure 0x15
#define ID_DAP_JTAG_IDCODE 0x16 // DAP Vendor Command IDs
#define ID_DAP_Vendor0 0x80
#define ID_DAP_Vendor1 0x81
#define ID_DAP_Vendor2 0x82
#define ID_DAP_Vendor3 0x83
#define ID_DAP_Vendor4 0x84
#define ID_DAP_Vendor5 0x85
#define ID_DAP_Vendor6 0x86
#define ID_DAP_Vendor7 0x87
#define ID_DAP_Vendor8 0x88
#define ID_DAP_Vendor9 0x89
#define ID_DAP_Vendor10 0x8A
#define ID_DAP_Vendor11 0x8B
#define ID_DAP_Vendor12 0x8C
#define ID_DAP_Vendor13 0x8D
#define ID_DAP_Vendor14 0x8E
#define ID_DAP_Vendor15 0x8F
#define ID_DAP_Vendor16 0x90
#define ID_DAP_Vendor17 0x91
#define ID_DAP_Vendor18 0x92
#define ID_DAP_Vendor19 0x93
#define ID_DAP_Vendor20 0x94
#define ID_DAP_Vendor21 0x95
#define ID_DAP_Vendor22 0x96
#define ID_DAP_Vendor23 0x97
#define ID_DAP_Vendor24 0x98
#define ID_DAP_Vendor25 0x99
#define ID_DAP_Vendor26 0x9A
#define ID_DAP_Vendor27 0x9B
#define ID_DAP_Vendor28 0x9C
#define ID_DAP_Vendor29 0x9D
#define ID_DAP_Vendor30 0x9E
#define ID_DAP_Vendor31 0x9F #define ID_DAP_Invalid 0xFF // DAP Status Code
#define DAP_OK 0
#define DAP_ERROR 0xFF // DAP ID
#define DAP_ID_VENDOR 1
#define DAP_ID_PRODUCT 2
#define DAP_ID_SER_NUM 3
#define DAP_ID_FW_VER 4
#define DAP_ID_DEVICE_VENDOR 5
#define DAP_ID_DEVICE_NAME 6
#define DAP_ID_CAPABILITIES 0xF0
#define DAP_ID_PACKET_COUNT 0xFE
#define DAP_ID_PACKET_SIZE 0xFF // DAP LEDs
#define DAP_LED_DEBUGGER_CONNECTED 0
#define DAP_LED_TARGET_RUNNING 1 // DAP Port
#define DAP_PORT_AUTODETECT 0 // Autodetect Port
#define DAP_PORT_DISABLED 0 // Port Disabled (I/O pins in High-Z)
#define DAP_PORT_SWD 1 // SWD Port (SWCLK, SWDIO) + nRESET
#define DAP_PORT_JTAG 2 // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET // DAP SWJ Pins
#define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK
#define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS
#define DAP_SWJ_TDI 2 // TDI
#define DAP_SWJ_TDO 3 // TDO
#define DAP_SWJ_nTRST 5 // nTRST
#define DAP_SWJ_nRESET 7 // nRESET // DAP Transfer Request
#define DAP_TRANSFER_APnDP (1<<0)
#define DAP_TRANSFER_RnW (1<<1)
#define DAP_TRANSFER_A2 (1<<2)
#define DAP_TRANSFER_A3 (1<<3)
#define DAP_TRANSFER_MATCH_VALUE (1<<4)
#define DAP_TRANSFER_MATCH_MASK (1<<5) // DAP Transfer Response
#define DAP_TRANSFER_OK (1<<0)
#define DAP_TRANSFER_WAIT (1<<1)
#define DAP_TRANSFER_FAULT (1<<2)
#define DAP_TRANSFER_ERROR (1<<3)
#define DAP_TRANSFER_MISMATCH (1<<4) // Debug Port Register Addresses
#define DP_IDCODE 0x00 // IDCODE Register (SW Read only)
#define DP_ABORT 0x00 // Abort Register (SW Write only)
#define DP_CTRL_STAT 0x04 // Control & Status
#define DP_WCR 0x04 // Wire Control Register (SW Only)
#define DP_SELECT 0x08 // Select Register (JTAG R/W & SW W)
#define DP_RESEND 0x08 // Resend (SW Read Only)
#define DP_RDBUFF 0x0C // Read Buffer (Read Only) // JTAG IR Codes
#define JTAG_ABORT 0x08
#define JTAG_DPACC 0x0A
#define JTAG_APACC 0x0B
#define JTAG_IDCODE 0x0E
#define JTAG_BYPASS 0x0F // JTAG Sequence Info
#define JTAG_SEQUENCE_TCK 0x3F // TCK count
#define JTAG_SEQUENCE_TMS 0x40 // TMS value
#define JTAG_SEQUENCE_TDO 0x80 // TDO capture #include <stddef.h>
#include <stdint.h> // DAP Data structure
typedef struct {
uint8_t debug_port; // Debug Port
uint8_t fast_clock; // Fast Clock Flag
uint32_t clock_delay; // Clock Delay
struct { // Transfer Configuration
uint8_t idle_cycles; // Idle cycles after transfer
uint16_t retry_count; // Number of retries after WAIT response
uint16_t match_retry; // Number of retries if read value does not match
uint32_t match_mask; // Match Mask
} transfer;
#if (DAP_SWD != 0)
struct { // SWD Configuration
uint8_t turnaround; // Turnaround period
uint8_t data_phase; // Always generate Data Phase
} swd_conf;
#endif
#if (DAP_JTAG != 0)
struct { // JTAG Device Chain
uint8_t count; // Number of devices
uint8_t index; // Device index (device at TDO has index 0)
#if (DAP_JTAG_DEV_CNT != 0)
uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits
uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR
uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR
#endif
} jtag_dev;
#endif
} DAP_Data_t; extern DAP_Data_t DAP_Data; // DAP Data
extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag // Functions
extern void SWJ_Sequence (uint32_t count, uint8_t *data);
extern void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo);
extern void JTAG_IR (uint32_t ir);
extern uint32_t JTAG_ReadIDCode (void);
extern void JTAG_WriteAbort (uint32_t data);
extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data);
extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); extern void Delayms (uint32_t delay); extern uint32_t DAP_ProcessVendorCommand (uint8_t *request, uint8_t *response); extern uint32_t DAP_ProcessCommand (uint8_t *request, uint8_t *response);
extern void DAP_Setup (void); // Configurable delay for clock generation
#define DELAY_SLOW_CYCLES 3 // Number of cycles for one iteration
static __forceinline void PIN_DELAY_SLOW (uint32_t delay) {
volatile int32_t count; count = delay;
while (--count);
} // Fixed delay for fast clock generation
#define DELAY_FAST_CYCLES 0 // Number of cycles
static __forceinline void PIN_DELAY_FAST (void) {
//__nop();
} #endif /* __DAP_H__ */
/******************************************************************************
* @file DAP.c
* @brief CMSIS-DAP Commands
* @version V1.00
* @date 31. May 2012
*
* @note
* Copyright (C) 2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/ #include <string.h>
#include "DAP_config.h"
#include "DAP.h" #define DAP_FW_VER "1.0" // Firmware Version #if (DAP_PACKET_SIZE < 64)
#error "Minimum Packet Size is 64"
#endif
#if (DAP_PACKET_SIZE > 32768)
#error "Maximum Packet Size is 32768"
#endif
#if (DAP_PACKET_COUNT < 1)
#error "Minimum Packet Count is 1"
#endif
#if (DAP_PACKET_COUNT > 255)
#error "Maximum Packet Count is 255"
#endif // Clock Macros #define MAX_SWJ_CLOCK(delay_cycles) \
(CPU_CLOCK/ / (IO_PORT_WRITE_CYCLES + delay_cycles)) #define CLOCK_DELAY(swj_clock) \
((CPU_CLOCK/ / swj_clock) - IO_PORT_WRITE_CYCLES) DAP_Data_t DAP_Data; // DAP Data
volatile uint8_t DAP_TransferAbort; // Trasfer Abort Flag #ifdef DAP_VENDOR
const char DAP_Vendor [] = DAP_VENDOR;
#endif
#ifdef DAP_PRODUCT
const char DAP_Product[] = DAP_PRODUCT;
#endif
#ifdef DAP_SER_NUM
const char DAP_SerNum [] = DAP_SER_NUM;
#endif
const char DAP_FW_Ver [] = DAP_FW_VER; #if TARGET_DEVICE_FIXED
const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR;
const char TargetDeviceName [] = TARGET_DEVICE_NAME;
#endif // Get DAP Information
// id: info identifier
// info: pointer to info data
// return: number of bytes in info data
static uint8_t DAP_Info(uint8_t id, uint8_t *info) {
uint8_t length = ; switch (id) {
case DAP_ID_VENDOR:
#ifdef DAP_VENDOR
memcpy(info, DAP_Vendor, sizeof(DAP_Vendor));
length = sizeof(DAP_Vendor);
#endif
break;
case DAP_ID_PRODUCT:
#ifdef DAP_PRODUCT
memcpy(info, DAP_Product, sizeof(DAP_Product));
length = sizeof(DAP_Product);
#endif
break;
case DAP_ID_SER_NUM:
#ifdef DAP_SER_NUM
memcpy(info, DAP_SerNum, sizeof(DAP_SerNum));
length = sizeof(DAP_SerNum);
#endif
break;
case DAP_ID_FW_VER:
memcpy(info, DAP_FW_Ver, sizeof(DAP_FW_Ver));
length = sizeof(DAP_FW_Ver);
break;
case DAP_ID_DEVICE_VENDOR:
#if TARGET_DEVICE_FIXED
memcpy(info, TargetDeviceVendor, sizeof(TargetDeviceVendor));
length = sizeof(DAP_Target_Device);
#endif
break;
case DAP_ID_DEVICE_NAME:
#if TARGET_DEVICE_FIXED
memcpy(info, TargetDeviceName, sizeof(TargetDeviceName));
length = sizeof(DAP_Target_Device);
#endif
break;
case DAP_ID_CAPABILITIES:
info[] = ((DAP_SWD != ) ? ( << ) : ) |
((DAP_JTAG != ) ? ( << ) : );
length = ;
break;
case DAP_ID_PACKET_SIZE:
info[] = (uint8_t)(DAP_PACKET_SIZE >> );
info[] = (uint8_t)(DAP_PACKET_SIZE >> );
length = ;
break;
case DAP_ID_PACKET_COUNT:
info[] = DAP_PACKET_COUNT;
length = ;
break;
} return (length);
} // Timer Functions #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) // Start Timer
static __inline void TIMER_START (uint32_t usec) {
SysTick->VAL = ;
SysTick->LOAD = usec * CPU_CLOCK/;
SysTick->CTRL = ( << SysTick_CTRL_ENABLE_Pos) |
( << SysTick_CTRL_CLKSOURCE_Pos);
} // Stop Timer
static __inline void TIMER_STOP (void) {
SysTick->CTRL = ;
} // Check if Timer expired
static __inline uint32_t TIMER_EXPIRED (void) {
return ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) ? : );
} #endif // Delay for specified time
// delay: delay time in ms
void Delayms(uint32_t delay) {
delay *= (CPU_CLOCK/ + (DELAY_SLOW_CYCLES-)) / DELAY_SLOW_CYCLES;
PIN_DELAY_SLOW(delay);
} // Process Delay command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_Delay(uint8_t *request, uint8_t *response) {
uint32_t delay; delay = *(request+) | (*(request+) << );
delay *= (CPU_CLOCK/ + (DELAY_SLOW_CYCLES-)) / DELAY_SLOW_CYCLES; PIN_DELAY_SLOW(delay); *response = DAP_OK;
return ();
} // Process LED command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_LED(uint8_t *request, uint8_t *response) { switch (*request) {
case DAP_LED_DEBUGGER_CONNECTED:
LED_CONNECTED_OUT((*(request+) & ));
break;
case DAP_LED_TARGET_RUNNING:
LED_RUNNING_OUT((*(request+) & ));
break;
default:
*response = DAP_ERROR;
return ();
} *response = DAP_OK;
return ();
} // Process Connect command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_Connect(uint8_t *request, uint8_t *response) {
uint32_t port; if (*request == DAP_PORT_AUTODETECT) {
port = DAP_DEFAULT_PORT;
} else {
port = *request;
} switch (port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
DAP_Data.debug_port = DAP_PORT_SWD;
PORT_SWD_SETUP();
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
DAP_Data.debug_port = DAP_PORT_JTAG;
PORT_JTAG_SETUP();
break;
#endif
default:
*response = DAP_PORT_DISABLED;
return ();
} *response = port;
return ();
} // Process Disconnect command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_Disconnect(uint8_t *response) { DAP_Data.debug_port = DAP_PORT_DISABLED;
PORT_OFF(); *response = DAP_OK;
return ();
} // Process Reset Target command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_ResetTarget(uint8_t *response) { *(response+) = RESET_TARGET();
*(response+) = DAP_OK;
return ();
} // Process SWJ Pins command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
static uint32_t DAP_SWJ_Pins(uint8_t *request, uint8_t *response) {
uint32_t value;
uint32_t select;
uint32_t wait; value = *(request+);
select = *(request+);
wait = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << ); if (select & ( << DAP_SWJ_SWCLK_TCK)) {
if (value & ( << DAP_SWJ_SWCLK_TCK)) {
PIN_SWCLK_TCK_SET();
} else {
PIN_SWCLK_TCK_CLR();
}
}
if (select & ( << DAP_SWJ_SWDIO_TMS)) {
if (value & ( << DAP_SWJ_SWDIO_TMS)) {
PIN_SWDIO_TMS_SET();
} else {
PIN_SWDIO_TMS_CLR();
}
}
if (select & ( << DAP_SWJ_TDI)) {
PIN_TDI_OUT(value >> DAP_SWJ_TDI);
}
if (select & ( << DAP_SWJ_nTRST)) {
PIN_nTRST_OUT(value >> DAP_SWJ_nTRST);
}
if (select & ( << DAP_SWJ_nRESET)) {
PIN_nRESET_OUT(value >> DAP_SWJ_nRESET);
} if (wait) {
if (wait > ) wait = ;
TIMER_START(wait);
do {
if (select & ( << DAP_SWJ_SWCLK_TCK)) {
if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) continue;
}
if (select & ( << DAP_SWJ_SWDIO_TMS)) {
if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) continue;
}
if (select & ( << DAP_SWJ_TDI)) {
if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) continue;
}
if (select & ( << DAP_SWJ_nTRST)) {
if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) continue;
}
if (select & ( << DAP_SWJ_nRESET)) {
if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) continue;
}
break;
} while (!TIMER_EXPIRED());
TIMER_STOP();
} value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) |
(PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) |
(PIN_TDI_IN() << DAP_SWJ_TDI) |
(PIN_TDO_IN() << DAP_SWJ_TDO) |
(PIN_nTRST_IN() << DAP_SWJ_nTRST) |
(PIN_nRESET_IN() << DAP_SWJ_nRESET); *response = (uint8_t)value;
return ();
}
#endif // Process SWJ Clock command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
static uint32_t DAP_SWJ_Clock(uint8_t *request, uint8_t *response) {
uint32_t clock;
uint32_t delay; clock = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << ); if (clock == ) {
*response = DAP_ERROR;
return ();
} if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) {
DAP_Data.fast_clock = ;
DAP_Data.clock_delay = ;
} else {
DAP_Data.fast_clock = ; delay = (CPU_CLOCK/ + (clock - )) / clock;
if (delay > IO_PORT_WRITE_CYCLES) {
delay -= IO_PORT_WRITE_CYCLES;
delay = (delay + (DELAY_SLOW_CYCLES - )) / DELAY_SLOW_CYCLES;
} else {
delay = ;
} DAP_Data.clock_delay = delay;
} *response = DAP_OK;
return ();
}
#endif // Process SWJ Sequence command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
static uint32_t DAP_SWJ_Sequence(uint8_t *request, uint8_t *response) {
uint32_t count; count = *request++;
if (count == ) count = ; SWJ_Sequence(count, request); *response = DAP_OK;
return ();
}
#endif // Process SWD Configure command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_SWD != 0)
static uint32_t DAP_SWD_Configure(uint8_t *request, uint8_t *response) {
uint8_t value; value = *request;
DAP_Data.swd_conf.turnaround = (value & 0x03) + ;
DAP_Data.swd_conf.data_phase = (value & 0x04) ? : ; *response = DAP_OK; return ();
}
#endif // Process SWD Abort command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_SWD != 0)
static uint32_t DAP_SWD_Abort(uint8_t *request, uint8_t *response) {
uint32_t data; if (DAP_Data.debug_port != DAP_PORT_SWD) {
*response = DAP_ERROR;
return ();
} // Load data (Ignore DAP index)
data = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << ); // Write Abort register
SWD_Transfer(DP_ABORT, &data);
*response = DAP_OK; return ();
}
#endif // Process JTAG Sequence command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_Sequence(uint8_t *request, uint8_t *response) {
uint32_t sequence_info;
uint32_t sequence_count;
uint32_t response_count;
uint32_t count; *response++ = DAP_OK;
response_count = ; sequence_count = *request++;
while (sequence_count--) {
sequence_info = *request++;
JTAG_Sequence(sequence_info, request, response);
count = sequence_info & JTAG_SEQUENCE_TCK;
if (count == ) count = ;
count = (count + ) / ;
request += count;
if (sequence_info & JTAG_SEQUENCE_TDO) {
response += count;
response_count += count;
}
} return (response_count);
}
#endif // Process JTAG Configure command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_Configure(uint8_t *request, uint8_t *response) {
uint32_t count;
uint32_t length;
uint32_t bits;
uint32_t n; count = *request++;
DAP_Data.jtag_dev.count = count; bits = ;
for (n = ; n < count; n++) {
length = *request++;
DAP_Data.jtag_dev.ir_length[n] = length;
DAP_Data.jtag_dev.ir_before[n] = bits;
bits += length;
}
for (n = ; n < count; n++) {
bits -= DAP_Data.jtag_dev.ir_length[n];
DAP_Data.jtag_dev.ir_after[n] = bits;
} *response = DAP_OK;
return ();
}
#endif // Process JTAG IDCODE command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_IDCode(uint8_t *request, uint8_t *response) {
uint32_t data; if (DAP_Data.debug_port != DAP_PORT_JTAG) {
err:*response = DAP_ERROR;
return ();
} // Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; // Select JTAG chain
JTAG_IR(JTAG_IDCODE); // Read IDCODE register
data = JTAG_ReadIDCode(); // Store Data
*(response+) = DAP_OK;
*(response+) = (uint8_t)(data >> );
*(response+) = (uint8_t)(data >> );
*(response+) = (uint8_t)(data >> );
*(response+) = (uint8_t)(data >> ); return (+);
}
#endif // Process JTAG Abort command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_Abort(uint8_t *request, uint8_t *response) {
uint32_t data; if (DAP_Data.debug_port != DAP_PORT_JTAG) {
err:*response = DAP_ERROR;
return ();
} // Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; // Select JTAG chain
JTAG_IR(JTAG_ABORT); // Load data
data = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << ); // Write Abort register
JTAG_WriteAbort(data);
*response = DAP_OK; return ();
}
#endif // Process Transfer Configure command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_TransferConfigure(uint8_t *request, uint8_t *response) { DAP_Data.transfer.idle_cycles = *(request+);
DAP_Data.transfer.retry_count = *(request+) | (*(request+) << );
DAP_Data.transfer.match_retry = *(request+) | (*(request+) << ); *response = DAP_OK; return ();
} // Process SWD Transfer command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_SWD != 0)
static uint32_t DAP_SWD_Transfer(uint8_t *request, uint8_t *response) {
uint32_t request_count;
uint32_t request_value;
uint32_t response_count;
uint32_t response_value;
uint8_t *response_head;
uint32_t post_read;
uint32_t check_write;
uint32_t match_value;
uint32_t match_retry;
uint32_t retry;
uint32_t data; response_count = ;
response_value = ;
response_head = response;
response += ; DAP_TransferAbort = ; post_read = ;
check_write = ; request++; // Ignore DAP index request_count = *request++;
while (request_count--) {
request_value = *request++;
if (request_value & DAP_TRANSFER_RnW) {
// Read register
if (post_read) {
// Read was posted before
retry = DAP_Data.transfer.retry_count;
if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) {
// Read previous AP data and post next AP read
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
} else {
// Read previous AP data
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
post_read = ;
}
if (response_value != DAP_TRANSFER_OK) break;
// Store previous AP data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
}
if (request_value & DAP_TRANSFER_MATCH_VALUE) {
// Read with value match
match_value = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << );
request += ;
match_retry = DAP_Data.transfer.match_retry;
if (request_value & DAP_TRANSFER_APnDP) {
// Post AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
}
do {
// Read register until its value matches or retry counter expires
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
} while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort);
if ((data & DAP_Data.transfer.match_mask) != match_value) {
response_value |= DAP_TRANSFER_MISMATCH;
}
if (response_value != DAP_TRANSFER_OK) break;
} else {
// Normal read
retry = DAP_Data.transfer.retry_count;
if (request_value & DAP_TRANSFER_APnDP) {
// Read AP register
if (post_read == ) {
// Post AP read
do {
response_value = SWD_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
post_read = ;
}
} else {
// Read DP register
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
// Store data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
}
}
check_write = ;
} else {
// Write register
if (post_read) {
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
post_read = ;
}
// Load data
data = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << );
request += ;
if (request_value & DAP_TRANSFER_MATCH_MASK) {
// Write match mask
DAP_Data.transfer.match_mask = data;
response_value = DAP_TRANSFER_OK;
} else {
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
check_write = ;
}
}
response_count++;
if (DAP_TransferAbort) break;
} if (response_value == DAP_TRANSFER_OK) {
if (post_read) {
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
} else if (check_write) {
// Check last write
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
}
} end:
*(response_head+) = (uint8_t)response_count;
*(response_head+) = (uint8_t)response_value; return (response - response_head);
}
#endif // Process JTAG Transfer command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_Transfer(uint8_t *request, uint8_t *response) {
uint32_t request_count;
uint32_t request_value;
uint32_t request_ir;
uint32_t response_count;
uint32_t response_value;
uint8_t *response_head;
uint32_t post_read;
uint32_t match_value;
uint32_t match_retry;
uint32_t retry;
uint32_t data;
uint32_t ir; response_count = ;
response_value = ;
response_head = response;
response += ; DAP_TransferAbort = ; ir = ;
post_read = ; // Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request++;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; request_count = *request++;
while (request_count--) {
request_value = *request++;
request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC;
if (request_value & DAP_TRANSFER_RnW) {
// Read register
if (post_read) {
// Read was posted before
retry = DAP_Data.transfer.retry_count;
if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == )) {
// Read previous data and post next read
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
} else {
// Select JTAG chain
if (ir != JTAG_DPACC) {
ir = JTAG_DPACC;
JTAG_IR(ir);
}
// Read previous data
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
post_read = ;
}
if (response_value != DAP_TRANSFER_OK) break;
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
}
if (request_value & DAP_TRANSFER_MATCH_VALUE) {
// Read with value match
match_value = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << );
request += ;
match_retry = DAP_Data.transfer.match_retry;
// Select JTAG chain
if (ir != request_ir) {
ir = request_ir;
JTAG_IR(ir);
}
// Post DP/AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
do {
// Read register until its value matches or retry counter expires
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
} while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort);
if ((data & DAP_Data.transfer.match_mask) != match_value) {
response_value |= DAP_TRANSFER_MISMATCH;
}
if (response_value != DAP_TRANSFER_OK) break;
} else {
// Normal read
if (post_read == ) {
// Select JTAG chain
if (ir != request_ir) {
ir = request_ir;
JTAG_IR(ir);
}
// Post DP/AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
post_read = ;
}
}
} else {
// Write register
if (post_read) {
// Select JTAG chain
if (ir != JTAG_DPACC) {
ir = JTAG_DPACC;
JTAG_IR(ir);
}
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
post_read = ;
}
// Load data
data = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << );
request += ;
if (request_value & DAP_TRANSFER_MATCH_MASK) {
// Write match mask
DAP_Data.transfer.match_mask = data;
response_value = DAP_TRANSFER_OK;
} else {
// Select JTAG chain
if (ir != request_ir) {
ir = request_ir;
JTAG_IR(ir);
}
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) break;
}
}
response_count++;
if (DAP_TransferAbort) break;
} if (response_value == DAP_TRANSFER_OK) {
// Select JTAG chain
if (ir != JTAG_DPACC) {
ir = JTAG_DPACC;
JTAG_IR(ir);
}
if (post_read) {
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
} else {
// Check last write
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
}
} end:
*(response_head+) = (uint8_t)response_count;
*(response_head+) = (uint8_t)response_value; return (response - response_head);
}
#endif // Process SWD Transfer Block command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_SWD != 0)
static uint32_t DAP_SWD_TransferBlock(uint8_t *request, uint8_t *response) {
uint32_t request_count;
uint32_t request_value;
uint32_t response_count;
uint32_t response_value;
uint8_t *response_head;
uint32_t retry;
uint32_t data; response_count = ;
response_value = ;
response_head = response;
response += ; DAP_TransferAbort = ; request++; // Ignore DAP index request_count = *request | (*(request+) << );
request += ;
if (request_count == ) goto end; request_value = *request++;
if (request_value & DAP_TRANSFER_RnW) {
// Read register block
if (request_value & DAP_TRANSFER_APnDP) {
// Post AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
}
while (request_count--) {
// Read DP/AP register
if ((request_count == ) && (request_value & DAP_TRANSFER_APnDP)) {
// Last AP read
request_value = DP_RDBUFF | DAP_TRANSFER_RnW;
}
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
// Store data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
response_count++;
}
} else {
// Write register block
while (request_count--) {
// Load data
data = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << );
request += ;
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
response_count++;
}
// Check last write
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
} end:
*(response_head+) = (uint8_t)(response_count >> );
*(response_head+) = (uint8_t)(response_count >> );
*(response_head+) = (uint8_t) response_value; return (response - response_head);
}
#endif // Process JTAG Transfer Block command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_TransferBlock(uint8_t *request, uint8_t *response) {
uint32_t request_count;
uint32_t request_value;
uint32_t response_count;
uint32_t response_value;
uint8_t *response_head;
uint32_t retry;
uint32_t data;
uint32_t ir; response_count = ;
response_value = ;
response_head = response;
response += ; DAP_TransferAbort = ; // Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request++;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; request_count = *request | (*(request+) << );
request += ;
if (request_count == ) goto end; request_value = *request++; // Select JTAG chain
ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC;
JTAG_IR(ir); if (request_value & DAP_TRANSFER_RnW) {
// Post read
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
// Read register block
while (request_count--) {
// Read DP/AP register
if (request_count == ) {
// Last read
if (ir != JTAG_DPACC) {
JTAG_IR(JTAG_DPACC);
}
request_value = DP_RDBUFF | DAP_TRANSFER_RnW;
}
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
// Store data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
*response++ = (uint8_t)(data >> );
response_count++;
}
} else {
// Write register block
while (request_count--) {
// Load data
data = (*(request+) << ) |
(*(request+) << ) |
(*(request+) << ) |
(*(request+) << );
request += ;
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) goto end;
response_count++;
}
// Check last write
if (ir != JTAG_DPACC) {
JTAG_IR(JTAG_DPACC);
}
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
} end:
*(response_head+) = (uint8_t)(response_count >> );
*(response_head+) = (uint8_t)(response_count >> );
*(response_head+) = (uint8_t) response_value; return (response - response_head);
}
#endif // Process DAP Vendor command and prepare response
// Default function (can be overridden)
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
__weak uint32_t DAP_ProcessVendorCommand(uint8_t *request, uint8_t *response) {
*response = ID_DAP_Invalid;
return ();
} // Process DAP command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
uint32_t DAP_ProcessCommand(uint8_t *request, uint8_t *response) {
uint32_t num; if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) {
return DAP_ProcessVendorCommand(request, response);
} *response++ = *request; switch (*request++) {
case ID_DAP_Info:
num = DAP_Info(*request, response+);
*response = num;
return ( + num);
case ID_DAP_LED:
num = DAP_LED(request, response);
break;
case ID_DAP_Connect:
num = DAP_Connect(request, response);
break;
case ID_DAP_Disconnect:
num = DAP_Disconnect(response);
break;
case ID_DAP_Delay:
num = DAP_Delay(request, response);
break;
case ID_DAP_ResetTarget:
num = DAP_ResetTarget(response);
break; #if ((DAP_SWD != 0) || (DAP_JTAG != 0))
case ID_DAP_SWJ_Pins:
num = DAP_SWJ_Pins(request, response);
break;
case ID_DAP_SWJ_Clock:
num = DAP_SWJ_Clock(request, response);
break;
case ID_DAP_SWJ_Sequence:
num = DAP_SWJ_Sequence(request, response);
break;
#else
case ID_DAP_SWJ_Pins:
case ID_DAP_SWJ_Clock:
case ID_DAP_SWJ_Sequence:
*response = DAP_ERROR;
return ();
#endif #if (DAP_SWD != 0)
case ID_DAP_SWD_Configure:
num = DAP_SWD_Configure(request, response);
break;
#else
case ID_DAP_SWD_Configure:
*response = DAP_ERROR;
return ();
#endif #if (DAP_JTAG != 0)
case ID_DAP_JTAG_Sequence:
num = DAP_JTAG_Sequence(request, response);
break;
case ID_DAP_JTAG_Configure:
num = DAP_JTAG_Configure(request, response);
break;
case ID_DAP_JTAG_IDCODE:
num = DAP_JTAG_IDCode(request, response);
break;
#else
case ID_DAP_JTAG_Sequence:
case ID_DAP_JTAG_Configure:
case ID_DAP_JTAG_IDCODE:
*response = DAP_ERROR;
return ();
#endif case ID_DAP_TransferConfigure:
num = DAP_TransferConfigure(request, response);
break; case ID_DAP_Transfer:
switch (DAP_Data.debug_port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
num = DAP_SWD_Transfer (request, response);
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
num = DAP_JTAG_Transfer(request, response);
break;
#endif
default:
*(response+) = ; // Response count
*(response+) = ; // Response value
num = ;
}
break; case ID_DAP_TransferBlock:
switch (DAP_Data.debug_port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
num = DAP_SWD_TransferBlock (request, response);
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
num = DAP_JTAG_TransferBlock(request, response);
break;
#endif
default:
*(response+) = ; // Response count [7:0]
*(response+) = ; // Response count[15:8]
*(response+) = ; // Response value
num = ;
}
break; case ID_DAP_WriteABORT:
switch (DAP_Data.debug_port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
num = DAP_SWD_Abort (request, response);
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
num = DAP_JTAG_Abort(request, response);
break;
#endif
default:
*response = DAP_ERROR;
return ();
}
break; default:
*(response-) = ID_DAP_Invalid;
return ();
} return ( + num);
} // Setup DAP
void DAP_Setup(void) { // Default settings (only non-zero values)
//DAP_Data.debug_port = 0;
//DAP_Data.fast_clock = 0;
DAP_Data.clock_delay = CLOCK_DELAY(DAP_DEFAULT_SWJ_CLOCK);
//DAP_Data.transfer.idle_cycles = 0;
DAP_Data.transfer.retry_count = ;
//DAP_Data.transfer.match_retry = 0;
//DAP_Data.transfer.match_mask = 0x000000;
#if (DAP_SWD != 0)
DAP_Data.swd_conf.turnaround = ;
//DAP_Data.swd_conf.data_phase = 0;
#endif
#if (DAP_JTAG != 0)
//DAP_Data.jtag_dev.count = 0;
#endif DAP_SETUP(); // Device specific setup
}
/******************************************************************************
* @file SW_DP.c
* @brief CMSIS-DAP SW DP I/O
* @version V1.00
* @date 31. May 2012
*
* @note
* Copyright (C) 2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/ #include "DAP_config.h"
#include "DAP.h" // SW Macros #define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR #define SW_CLOCK_CYCLE() \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
PIN_SWCLK_SET(); \
PIN_DELAY() #define SW_WRITE_BIT(bit) \
PIN_SWDIO_OUT(bit); \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
PIN_SWCLK_SET(); \
PIN_DELAY() #define SW_READ_BIT(bit) \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
bit = PIN_SWDIO_IN(); \
PIN_SWCLK_SET(); \
PIN_DELAY() #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) // Generate SWJ Sequence
// count: sequence bit count
// data: pointer to sequence bit data
// return: none
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
void SWJ_Sequence (uint32_t count, uint8_t *data) {
uint32_t val;
uint32_t n; val = ;
n = ;
while (count--) {
if (n == ) {
val = *data++;
n = ;
}
if (val & ) {
PIN_SWDIO_TMS_SET();
} else {
PIN_SWDIO_TMS_CLR();
}
SW_CLOCK_CYCLE();
val >>= ;
n--;
}
}
#endif #if (DAP_SWD != 0) // SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
#define SWD_TransferFunction(speed) /**/ \
uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \
uint32_t ack; \
uint32_t bit; \
uint32_t val; \
uint32_t parity; \
\
uint32_t n; \
\
/* Packet Request */ \
parity = ; \
SW_WRITE_BIT(); /* Start Bit */ \
bit = request >> ; \
SW_WRITE_BIT(bit); /* APnDP Bit */ \
parity += bit; \
bit = request >> ; \
SW_WRITE_BIT(bit); /* RnW Bit */ \
parity += bit; \
bit = request >> ; \
SW_WRITE_BIT(bit); /* A2 Bit */ \
parity += bit; \
bit = request >> ; \
SW_WRITE_BIT(bit); /* A3 Bit */ \
parity += bit; \
SW_WRITE_BIT(parity); /* Parity Bit */ \
SW_WRITE_BIT(); /* Stop Bit */ \
SW_WRITE_BIT(); /* Park Bit */ \
\
/* Turnaround */ \
PIN_SWDIO_OUT_DISABLE(); \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
\
/* Acknowledge response */ \
SW_READ_BIT(bit); \
ack = bit << ; \
SW_READ_BIT(bit); \
ack |= bit << ; \
SW_READ_BIT(bit); \
ack |= bit << ; \
\
if (ack == DAP_TRANSFER_OK) { /* OK response */ \
/* Data transfer */ \
if (request & DAP_TRANSFER_RnW) { \
/* Read data */ \
val = ; \
parity = ; \
for (n = ; n; n--) { \
SW_READ_BIT(bit); /* Read RDATA[0:31] */ \
parity += bit; \
val >>= ; \
val |= bit << ; \
} \
SW_READ_BIT(bit); /* Read Parity */ \
if ((parity ^ bit) & ) { \
ack = DAP_TRANSFER_ERROR; \
} \
if (data) *data = val; \
/* Turnaround */ \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
PIN_SWDIO_OUT_ENABLE(); \
} else { \
/* Turnaround */ \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
PIN_SWDIO_OUT_ENABLE(); \
/* Write data */ \
val = *data; \
parity = ; \
for (n = ; n; n--) { \
SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \
parity += val; \
val >>= ; \
} \
SW_WRITE_BIT(parity); /* Write Parity Bit */ \
} \
/* Idle cycles */ \
n = DAP_Data.transfer.idle_cycles; \
if (n) { \
PIN_SWDIO_OUT(); \
for (; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
} \
PIN_SWDIO_OUT(); \
return (ack); \
} \
\
if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \
/* WAIT or FAULT response */ \
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != )) { \
for (n = +; n; n--) { \
SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \
} \
} \
/* Turnaround */ \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
PIN_SWDIO_OUT_ENABLE(); \
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == )) { \
PIN_SWDIO_OUT(); \
for (n = +; n; n--) { \
SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \
} \
} \
PIN_SWDIO_OUT(); \
return (ack); \
} \
\
/* Protocol error */ \
for (n = DAP_Data.swd_conf.turnaround + + ; n; n--) { \
SW_CLOCK_CYCLE(); /* Back off data phase */ \
} \
PIN_SWDIO_OUT(); \
return (ack); \
} #undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_FAST()
SWD_TransferFunction(Fast); #undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
SWD_TransferFunction(Slow); // SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
uint8_t SWD_Transfer(uint32_t request, uint32_t *data) {
if (DAP_Data.fast_clock) {
return SWD_TransferFast(request, data);
} else {
return SWD_TransferSlow(request, data);
}
} #endif /* (DAP_SWD != 0) */
/******************************************************************************
* @file JTAG_DP.c
* @brief CMSIS-DAP JTAG DP I/O
* @version V1.00
* @date 31. May 2012
*
* @note
* Copyright (C) 2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/ #include "DAP_config.h"
#include "DAP.h" // JTAG Macros #define PIN_TCK_SET PIN_SWCLK_TCK_SET
#define PIN_TCK_CLR PIN_SWCLK_TCK_CLR
#define PIN_TMS_SET PIN_SWDIO_TMS_SET
#define PIN_TMS_CLR PIN_SWDIO_TMS_CLR #define JTAG_CYCLE_TCK() \
PIN_TCK_CLR(); \
PIN_DELAY(); \
PIN_TCK_SET(); \
PIN_DELAY() #define JTAG_CYCLE_TDI(tdi) \
PIN_TDI_OUT(tdi); \
PIN_TCK_CLR(); \
PIN_DELAY(); \
PIN_TCK_SET(); \
PIN_DELAY() #define JTAG_CYCLE_TDO(tdo) \
PIN_TCK_CLR(); \
PIN_DELAY(); \
tdo = PIN_TDO_IN(); \
PIN_TCK_SET(); \
PIN_DELAY() #define JTAG_CYCLE_TDIO(tdi,tdo) \
PIN_TDI_OUT(tdi); \
PIN_TCK_CLR(); \
PIN_DELAY(); \
tdo = PIN_TDO_IN(); \
PIN_TCK_SET(); \
PIN_DELAY() #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) #if (DAP_JTAG != 0) // Generate JTAG Sequence
// info: sequence information
// tdi: pointer to TDI generated data
// tdo: pointer to TDO captured data
// return: none
void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo) {
uint32_t i_val;
uint32_t o_val;
uint32_t bit;
uint32_t n, k; n = info & JTAG_SEQUENCE_TCK;
if (n == ) n = ; if (info & JTAG_SEQUENCE_TMS) {
PIN_TMS_SET();
} else {
PIN_TMS_CLR();
} while (n) {
i_val = *tdi++;
o_val = ;
for (k = ; k && n; k--, n--) {
JTAG_CYCLE_TDIO(i_val, bit);
i_val >>= ;
o_val >>= ;
o_val |= bit << ;
}
o_val >>= k;
if (info & JTAG_SEQUENCE_TDO) {
*tdo++ = o_val;
}
}
} // JTAG Set IR
// ir: IR value
// return: none
#define JTAG_IR_Function(speed) /**/ \
void JTAG_IR_##speed (uint32_t ir) { \
uint32_t n; \
\
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \
JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Capture-IR */ \
JTAG_CYCLE_TCK(); /* Shift-IR */ \
\
PIN_TDI_OUT(); \
for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass before data */ \
} \
for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - ; n; n--) { \
JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \
ir >>= ; \
} \
n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \
if (n) { \
JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \
PIN_TDI_OUT(); \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \
} \
\
JTAG_CYCLE_TCK(); /* Update-IR */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Idle */ \
PIN_TDI_OUT(); \
} // JTAG Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
#define JTAG_TransferFunction(speed) /**/ \
uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \
uint32_t ack; \
uint32_t bit; \
uint32_t val; \
uint32_t n; \
\
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Capture-DR */ \
JTAG_CYCLE_TCK(); /* Shift-DR */ \
\
for (n = DAP_Data.jtag_dev.index; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass before data */ \
} \
\
JTAG_CYCLE_TDIO(request >> , bit); /* Set RnW, Get ACK.0 */ \
ack = bit << ; \
JTAG_CYCLE_TDIO(request >> , bit); /* Set A2, Get ACK.1 */ \
ack |= bit << ; \
JTAG_CYCLE_TDIO(request >> , bit); /* Set A3, Get ACK.2 */ \
ack |= bit << ; \
\
if (ack != DAP_TRANSFER_OK) { \
/* Exit on error */ \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Exit1-DR */ \
goto exit; \
} \
\
if (request & DAP_TRANSFER_RnW) { \
/* Read Transfer */ \
val = ; \
for (n = ; n; n--) { \
JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \
val |= bit << ; \
val >>= ; \
} \
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - ; \
if (n) { \
JTAG_CYCLE_TDO(bit); /* Get D31 */ \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \
} \
val |= bit << ; \
if (data) *data = val; \
} else { \
/* Write Transfer */ \
val = *data; \
for (n = ; n; n--) { \
JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \
val >>= ; \
} \
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - ; \
if (n) { \
JTAG_CYCLE_TDI(val); /* Set D31 */ \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \
} \
} \
\
exit: \
JTAG_CYCLE_TCK(); /* Update-DR */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Idle */ \
PIN_TDI_OUT(); \
\
/* Idle cycles */ \
n = DAP_Data.transfer.idle_cycles; \
while (n--) { \
JTAG_CYCLE_TCK(); /* Idle */ \
} \
\
return (ack); \
} #undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_FAST()
JTAG_IR_Function(Fast);
JTAG_TransferFunction(Fast); #undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
JTAG_IR_Function(Slow);
JTAG_TransferFunction(Slow); // JTAG Read IDCODE register
// return: value read
uint32_t JTAG_ReadIDCode (void) {
uint32_t bit;
uint32_t val;
uint32_t n; PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Select-DR-Scan */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Capture-DR */
JTAG_CYCLE_TCK(); /* Shift-DR */ for (n = DAP_Data.jtag_dev.index; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass before data */
} val = ;
for (n = ; n; n--) {
JTAG_CYCLE_TDO(bit); /* Get D0..D30 */
val |= bit << ;
val >>= ;
}
PIN_TMS_SET();
JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */
val |= bit << ; JTAG_CYCLE_TCK(); /* Update-DR */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Idle */ return (val);
} // JTAG Write ABORT register
// data: value to write
// return: none
void JTAG_WriteAbort (uint32_t data) {
uint32_t n; PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Select-DR-Scan */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Capture-DR */
JTAG_CYCLE_TCK(); /* Shift-DR */ for (n = DAP_Data.jtag_dev.index; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass before data */
} PIN_TDI_OUT();
JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */
JTAG_CYCLE_TCK(); /* Set A2=0 */
JTAG_CYCLE_TCK(); /* Set A3=0 */ for (n = ; n; n--) {
JTAG_CYCLE_TDI(data); /* Set D0..D30 */
data >>= ;
}
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - ;
if (n) {
JTAG_CYCLE_TDI(data); /* Set D31 */
for (--n; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass after data */
}
PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */
} else {
PIN_TMS_SET();
JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */
} JTAG_CYCLE_TCK(); /* Update-DR */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Idle */
PIN_TDI_OUT();
} // JTAG Set IR
// ir: IR value
// return: none
void JTAG_IR (uint32_t ir) {
if (DAP_Data.fast_clock) {
JTAG_IR_Fast(ir);
} else {
JTAG_IR_Slow(ir);
}
} // JTAG Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) {
if (DAP_Data.fast_clock) {
return JTAG_TransferFast(request, data);
} else {
return JTAG_TransferSlow(request, data);
}
} #endif /* (DAP_JTAG != 0) */

CMSIS-DAP USB HID Firmware for NXP LPC-Link-II board.

CMSIS-DAP USB HID Firmware for Freescale OpenSDA.

CMSIS-DAP USB HID Firmware for STM32F103.

CMSIS-DAP调试器的更多相关文章

  1. STM32CubeIDE下载安装-GPIO基本配置操作-Debug调试(基于CMSIS DAP Debug)

    1.在ST官网下载STM32CubeIDE而不是STM32CubeMX,并且STM32CubeIDE是免费的.(STM32CubeIDE不支持中文路径,不然编译会出错) 2.如果你用的是keil开发环 ...

  2. STM32开发笔记之——CMSIS DAP

    都说开发stm32都是使用kail iar+jatg/swd的方式,然而arm公司已经开发出了CMSIS DAP的开源下载工具,全称是CoreSight Debug Access Port,网络上有大 ...

  3. 选择目录,选择文件夹的COM组件问题。在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常。

    异常: 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式.请确保您的 Main 函数带有 STAThreadAttribute 标记. 只有将调试器附加到该进程才会引发此异常. ...

  4. [连载]《C#通讯(串口和网络)框架的设计与实现》- 11.调试器的设计

    目       录 第十一章     调试器设计... 2 11.1         调试接口... 2 11.2         界面方式调试... 3 11.3         命令行方式调试.. ...

  5. 带调试器(Debugger)的ILSpy(2.2.0.1738)

    2015-03-13 09:40更新: 感谢@dark89757园友提出的调试时不能查看变量的问题. 源码已修改,并提交到了github. 请查看最新发布,二进制文件和源码都在这里: 调试时可查看变量 ...

  6. Linux C编程学习之开发工具2---GDB调试器

    简介 GDB是一个功能强大的交互式程序调试工具,主要工作在字符界面下. GDB不仅可以用来调试C/C++ 语言编写的程序,还可以用来调试 Pascal.Objective-C,以及Fortran等语言 ...

  7. VS2003"无法启动调试 没有正确安装调试器"的解决办法

    VS2003"无法启动调试 没有正确安装调试器"的解决方法 在用VS2003做项目的时候,经常调试程序,但是有时候回出现如下问题“无法启动调试,没有正确安装调试器,请运行安装程序或 ...

  8. 昨天晚上画了个带apple的图:ide插件与php和xdebug通信原理图,周末写1个调试器。

    昨天晚上画了个带apple的图:ide插件与php和xdebug通信原理图,周末写1个调试器.

  9. 总是弹出visual studio 实时调试器 三种解决办法

    最近服务器老是弹出visual studio 实时调试器很是郁闷呀.关还关不掉.怎么解决呢 ,现像如下图所示: 下面我们一起来分析一下这种情况的原因: 弹出应用程序: Visual Studio 实时 ...

  10. C#调试器导航

    本快速入门演示如何在 Visual Studio 调试会话中导航,以及如何在会话中查看和更改程序状态. 本 快速入门适用于不熟悉用 Visual Studio 进行调试的开发人员,以及要详细了解在 V ...

随机推荐

  1. linux 修改时间 - [命令操作]

    我们一般使用“date -s”命令来修改系统时间.比如将系统时间设定成1996年6月10日的命令如下. #date -s 06/10/96 将系统时间设定成下午1点12分0秒的命令如下. #date ...

  2. Pitcher Rotation

    题意: n个人m个对手给出每个人能战胜每个敌人的概率,现在有g个比赛,每个人赛完后要休息4天(可重复用),求能获得胜利的最大期望个数. 分析: 因为只有每个人5天就能用一次,所以对于每个人来说,只有得 ...

  3. APP测试时不可忽视搭建代理服务器抓包测试的必要性

    这几天测的一个app,后台从已有服务器搬迁到了阿里云,接口api之类的都没有变化,但测试时发现客户端始终无法使用,每次点击都无法获得服务器反馈 用python编写脚本调接口,没问题,返回数据一切正常, ...

  4. 句柄(handle)

    < Back 句柄,在windows编程中用来标识: *.模块(module) *.任务(task) *.实例(instance) *.文件(file) *.内存块(block of memor ...

  5. CentOS下安装R

    R的Windows版本有直接的安装包,直接下载安装很方便,但是对于CentOS6以上,不能直接通过yum 安装R,需要自己编译. 1. 在编译之前,用yum安装各种软件 (1)安装gcc > y ...

  6. 【一段日子荟萃】where should I go.

    当<UNIX环境高级编程>和<鸟哥的私房菜>到我的桌头的时候,我忽然产生了厌倦的心. NO,我不是想做这个,我不是想学习这个操作系统的结构和接口. 我想些一个操作系统,更一般的 ...

  7. 分布式文件系统--GFS

    分布式文件系统 分布式文件系统:当数据集的大小超过一台独立物理计算机的存储能力时,就有必要对它进行分区(partition)并存储到若干台单独的计算机上.管理网络中夸多台计算机存储的文件系统.这种系统 ...

  8. Arduino1.7.10在Ubuntu下创建快捷方式

    从官网下载的arduino1.7.10版本没有快捷方式只有可执行文件arduino,通过下面的方法可以创建快捷方式 打开链接:http://www.easyicon.net/1171938-ardui ...

  9. Educational Codeforces Round 5 A. Comparing Two Long Integers

    A. Comparing Two Long Integers time limit per test 2 seconds memory limit per test 256 megabytes inp ...

  10. ZOJ-3349 Special Subsequence 线段树优化DP

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3349 题意:给定一个数列,序列A是一个满足|Ai-Ai-1| & ...