1 /******************************************************************************
\r
3 * @brief CMSIS-DAP Commands
\r
8 * Copyright (C) 2012 ARM Limited. All rights reserved.
\r
11 * ARM Limited (ARM) is supplying this software for use with Cortex-M
\r
12 * processor based microcontrollers.
\r
15 * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
\r
16 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
\r
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
\r
18 * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
\r
19 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
\r
21 ******************************************************************************/
\r
24 #include "DAP_config.h"
\r
28 #define DAP_FW_VER "1.0" // Firmware Version
\r
31 #if (DAP_PACKET_SIZE < 64)
\r
32 #error "Minimum Packet Size is 64"
\r
34 #if (DAP_PACKET_SIZE > 32768)
\r
35 #error "Maximum Packet Size is 32768"
\r
37 #if (DAP_PACKET_COUNT < 1)
\r
38 #error "Minimum Packet Count is 1"
\r
40 #if (DAP_PACKET_COUNT > 255)
\r
41 #error "Maximum Packet Count is 255"
\r
47 #define MAX_SWJ_CLOCK(delay_cycles) \
\r
48 (CPU_CLOCK/2 / (IO_PORT_WRITE_CYCLES + delay_cycles))
\r
50 #define CLOCK_DELAY(swj_clock) \
\r
51 ((CPU_CLOCK/2 / swj_clock) - IO_PORT_WRITE_CYCLES)
\r
54 DAP_Data_t DAP_Data; // DAP Data
\r
55 volatile uint8_t DAP_TransferAbort; // Trasfer Abort Flag
\r
59 const char DAP_Vendor [] = DAP_VENDOR;
\r
62 const char DAP_Product[] = DAP_PRODUCT;
\r
65 const char DAP_SerNum [] = DAP_SER_NUM;
\r
67 const char DAP_FW_Ver [] = DAP_FW_VER;
\r
69 #if TARGET_DEVICE_FIXED
\r
70 const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR;
\r
71 const char TargetDeviceName [] = TARGET_DEVICE_NAME;
\r
75 // Get DAP Information
\r
76 // id: info identifier
\r
77 // info: pointer to info data
\r
78 // return: number of bytes in info data
\r
79 static uint8_t DAP_Info(uint8_t id, uint8_t *info) {
\r
85 memcpy(info, DAP_Vendor, sizeof(DAP_Vendor));
\r
86 length = sizeof(DAP_Vendor);
\r
89 case DAP_ID_PRODUCT:
\r
91 memcpy(info, DAP_Product, sizeof(DAP_Product));
\r
92 length = sizeof(DAP_Product);
\r
95 case DAP_ID_SER_NUM:
\r
97 memcpy(info, DAP_SerNum, sizeof(DAP_SerNum));
\r
98 length = sizeof(DAP_SerNum);
\r
101 case DAP_ID_FW_VER:
\r
102 memcpy(info, DAP_FW_Ver, sizeof(DAP_FW_Ver));
\r
103 length = sizeof(DAP_FW_Ver);
\r
105 case DAP_ID_DEVICE_VENDOR:
\r
106 #if TARGET_DEVICE_FIXED
\r
107 memcpy(info, TargetDeviceVendor, sizeof(TargetDeviceVendor));
\r
108 length = sizeof(TargetDeviceVendor);
\r
111 case DAP_ID_DEVICE_NAME:
\r
112 #if TARGET_DEVICE_FIXED
\r
113 memcpy(info, TargetDeviceName, sizeof(TargetDeviceName));
\r
114 length = sizeof(TargetDeviceName);
\r
117 case DAP_ID_CAPABILITIES:
\r
118 info[0] = ((DAP_SWD != 0) ? (1 << 0) : 0) |
\r
119 ((DAP_JTAG != 0) ? (1 << 1) : 0);
\r
122 case DAP_ID_PACKET_SIZE:
\r
123 info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0);
\r
124 info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8);
\r
127 case DAP_ID_PACKET_COUNT:
\r
128 info[0] = DAP_PACKET_COUNT;
\r
139 #if ((DAP_SWD != 0) || (DAP_JTAG != 0))
\r
142 static __inline void TIMER_START (uint32_t usec) {
\r
144 SysTick->LOAD = usec * CPU_CLOCK/1000000;
\r
145 SysTick->CTRL = (1 << SysTick_CTRL_ENABLE_Pos) |
\r
146 (1 << SysTick_CTRL_CLKSOURCE_Pos);
\r
150 static __inline void TIMER_STOP (void) {
\r
154 // Check if Timer expired
\r
155 static __inline uint32_t TIMER_EXPIRED (void) {
\r
156 return ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) ? 1 : 0);
\r
162 // Delay for specified time
\r
163 // delay: delay time in ms
\r
164 void Delayms(uint32_t delay) {
\r
165 delay *= (CPU_CLOCK/1000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES;
\r
166 PIN_DELAY_SLOW(delay);
\r
170 // Process Delay command and prepare response
\r
171 // request: pointer to request data
\r
172 // response: pointer to response data
\r
173 // return: number of bytes in response
\r
174 static uint32_t DAP_Delay(uint8_t *request, uint8_t *response) {
\r
177 delay = *(request+0) | (*(request+1) << 8);
\r
178 delay *= (CPU_CLOCK/1000000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES;
\r
180 PIN_DELAY_SLOW(delay);
\r
182 *response = DAP_OK;
\r
187 // Process LED command and prepare response
\r
188 // request: pointer to request data
\r
189 // response: pointer to response data
\r
190 // return: number of bytes in response
\r
191 static uint32_t DAP_LED(uint8_t *request, uint8_t *response) {
\r
193 switch (*request) {
\r
194 case DAP_LED_DEBUGGER_CONNECTED:
\r
195 LED_CONNECTED_OUT((*(request+1) & 1));
\r
197 case DAP_LED_TARGET_RUNNING:
\r
198 LED_RUNNING_OUT((*(request+1) & 1));
\r
201 *response = DAP_ERROR;
\r
205 *response = DAP_OK;
\r
210 // Process Connect command and prepare response
\r
211 // request: pointer to request data
\r
212 // response: pointer to response data
\r
213 // return: number of bytes in response
\r
214 static uint32_t DAP_Connect(uint8_t *request, uint8_t *response) {
\r
217 if (*request == DAP_PORT_AUTODETECT) {
\r
218 port = DAP_DEFAULT_PORT;
\r
226 DAP_Data.debug_port = DAP_PORT_SWD;
\r
230 #if (DAP_JTAG != 0)
\r
231 case DAP_PORT_JTAG:
\r
232 DAP_Data.debug_port = DAP_PORT_JTAG;
\r
237 *response = DAP_PORT_DISABLED;
\r
246 // Process Disconnect command and prepare response
\r
247 // request: pointer to request data
\r
248 // response: pointer to response data
\r
249 // return: number of bytes in response
\r
250 static uint32_t DAP_Disconnect(uint8_t *response) {
\r
252 DAP_Data.debug_port = DAP_PORT_DISABLED;
\r
255 *response = DAP_OK;
\r
260 // Process Reset Target command and prepare response
\r
261 // request: pointer to request data
\r
262 // response: pointer to response data
\r
263 // return: number of bytes in response
\r
264 static uint32_t DAP_ResetTarget(uint8_t *response) {
\r
266 *(response+1) = RESET_TARGET();
\r
267 *(response+0) = DAP_OK;
\r
272 // Process SWJ Pins command and prepare response
\r
273 // request: pointer to request data
\r
274 // response: pointer to response data
\r
275 // return: number of bytes in response
\r
276 #if ((DAP_SWD != 0) || (DAP_JTAG != 0))
\r
277 static uint32_t DAP_SWJ_Pins(uint8_t *request, uint8_t *response) {
\r
282 value = *(request+0);
\r
283 select = *(request+1);
\r
284 wait = (*(request+2) << 0) |
\r
285 (*(request+3) << 8) |
\r
286 (*(request+4) << 16) |
\r
287 (*(request+5) << 24);
\r
289 if (select & (1 << DAP_SWJ_SWCLK_TCK)) {
\r
290 if (value & (1 << DAP_SWJ_SWCLK_TCK)) {
\r
291 PIN_SWCLK_TCK_SET();
\r
293 PIN_SWCLK_TCK_CLR();
\r
296 if (select & (1 << DAP_SWJ_SWDIO_TMS)) {
\r
297 if (value & (1 << DAP_SWJ_SWDIO_TMS)) {
\r
298 PIN_SWDIO_TMS_SET();
\r
300 PIN_SWDIO_TMS_CLR();
\r
303 if (select & (1 << DAP_SWJ_TDI)) {
\r
304 PIN_TDI_OUT(value >> DAP_SWJ_TDI);
\r
306 if (select & (1 << DAP_SWJ_nTRST)) {
\r
307 PIN_nTRST_OUT(value >> DAP_SWJ_nTRST);
\r
309 if (select & (1 << DAP_SWJ_nRESET)) {
\r
310 PIN_nRESET_OUT(value >> DAP_SWJ_nRESET);
\r
314 if (wait > 3000000) wait = 3000000;
\r
317 if (select & (1 << DAP_SWJ_SWCLK_TCK)) {
\r
318 if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) continue;
\r
320 if (select & (1 << DAP_SWJ_SWDIO_TMS)) {
\r
321 if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) continue;
\r
323 if (select & (1 << DAP_SWJ_TDI)) {
\r
324 if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) continue;
\r
326 if (select & (1 << DAP_SWJ_nTRST)) {
\r
327 if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) continue;
\r
329 if (select & (1 << DAP_SWJ_nRESET)) {
\r
330 if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) continue;
\r
333 } while (!TIMER_EXPIRED());
\r
337 value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) |
\r
338 (PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) |
\r
339 (PIN_TDI_IN() << DAP_SWJ_TDI) |
\r
340 (PIN_TDO_IN() << DAP_SWJ_TDO) |
\r
341 (PIN_nTRST_IN() << DAP_SWJ_nTRST) |
\r
342 (PIN_nRESET_IN() << DAP_SWJ_nRESET);
\r
344 *response = (uint8_t)value;
\r
350 // Process SWJ Clock command and prepare response
\r
351 // request: pointer to request data
\r
352 // response: pointer to response data
\r
353 // return: number of bytes in response
\r
354 #if ((DAP_SWD != 0) || (DAP_JTAG != 0))
\r
355 static uint32_t DAP_SWJ_Clock(uint8_t *request, uint8_t *response) {
\r
359 clock = (*(request+0) << 0) |
\r
360 (*(request+1) << 8) |
\r
361 (*(request+2) << 16) |
\r
362 (*(request+3) << 24);
\r
365 *response = DAP_ERROR;
\r
369 if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) {
\r
370 DAP_Data.fast_clock = 1;
\r
371 DAP_Data.clock_delay = 1;
\r
373 DAP_Data.fast_clock = 0;
\r
375 delay = (CPU_CLOCK/2 + (clock - 1)) / clock;
\r
376 if (delay > IO_PORT_WRITE_CYCLES) {
\r
377 delay -= IO_PORT_WRITE_CYCLES;
\r
378 delay = (delay + (DELAY_SLOW_CYCLES - 1)) / DELAY_SLOW_CYCLES;
\r
383 DAP_Data.clock_delay = delay;
\r
386 *response = DAP_OK;
\r
392 // Process SWJ Sequence command and prepare response
\r
393 // request: pointer to request data
\r
394 // response: pointer to response data
\r
395 // return: number of bytes in response
\r
396 #if ((DAP_SWD != 0) || (DAP_JTAG != 0))
\r
397 static uint32_t DAP_SWJ_Sequence(uint8_t *request, uint8_t *response) {
\r
400 count = *request++;
\r
401 if (count == 0) count = 256;
\r
403 SWJ_Sequence(count, request);
\r
405 *response = DAP_OK;
\r
411 // Process SWD Configure command and prepare response
\r
412 // request: pointer to request data
\r
413 // response: pointer to response data
\r
414 // return: number of bytes in response
\r
416 static uint32_t DAP_SWD_Configure(uint8_t *request, uint8_t *response) {
\r
420 DAP_Data.swd_conf.turnaround = (value & 0x03) + 1;
\r
421 DAP_Data.swd_conf.data_phase = (value & 0x04) ? 1 : 0;
\r
423 *response = DAP_OK;
\r
430 // Process SWD Abort command and prepare response
\r
431 // request: pointer to request data
\r
432 // response: pointer to response data
\r
433 // return: number of bytes in response
\r
435 static uint32_t DAP_SWD_Abort(uint8_t *request, uint8_t *response) {
\r
438 if (DAP_Data.debug_port != DAP_PORT_SWD) {
\r
439 *response = DAP_ERROR;
\r
443 // Load data (Ignore DAP index)
\r
444 data = (*(request+1) << 0) |
\r
445 (*(request+2) << 8) |
\r
446 (*(request+3) << 16) |
\r
447 (*(request+4) << 24);
\r
449 // Write Abort register
\r
450 SWD_Transfer(DP_ABORT, &data);
\r
451 *response = DAP_OK;
\r
458 // Process JTAG Sequence command and prepare response
\r
459 // request: pointer to request data
\r
460 // response: pointer to response data
\r
461 // return: number of bytes in response
\r
462 #if (DAP_JTAG != 0)
\r
463 static uint32_t DAP_JTAG_Sequence(uint8_t *request, uint8_t *response) {
\r
464 uint32_t sequence_info;
\r
465 uint32_t sequence_count;
\r
466 uint32_t response_count;
\r
469 *response++ = DAP_OK;
\r
470 response_count = 1;
\r
472 sequence_count = *request++;
\r
473 while (sequence_count--) {
\r
474 sequence_info = *request++;
\r
475 JTAG_Sequence(sequence_info, request, response);
\r
476 count = sequence_info & JTAG_SEQUENCE_TCK;
\r
477 if (count == 0) count = 64;
\r
478 count = (count + 7) / 8;
\r
480 if (sequence_info & JTAG_SEQUENCE_TDO) {
\r
482 response_count += count;
\r
486 return (response_count);
\r
491 // Process JTAG Configure command and prepare response
\r
492 // request: pointer to request data
\r
493 // response: pointer to response data
\r
494 // return: number of bytes in response
\r
495 #if (DAP_JTAG != 0)
\r
496 static uint32_t DAP_JTAG_Configure(uint8_t *request, uint8_t *response) {
\r
502 count = *request++;
\r
503 DAP_Data.jtag_dev.count = count;
\r
506 for (n = 0; n < count; n++) {
\r
507 length = *request++;
\r
508 DAP_Data.jtag_dev.ir_length[n] = length;
\r
509 DAP_Data.jtag_dev.ir_before[n] = bits;
\r
512 for (n = 0; n < count; n++) {
\r
513 bits -= DAP_Data.jtag_dev.ir_length[n];
\r
514 DAP_Data.jtag_dev.ir_after[n] = bits;
\r
517 *response = DAP_OK;
\r
523 // Process JTAG IDCODE command and prepare response
\r
524 // request: pointer to request data
\r
525 // response: pointer to response data
\r
526 // return: number of bytes in response
\r
527 #if (DAP_JTAG != 0)
\r
528 static uint32_t DAP_JTAG_IDCode(uint8_t *request, uint8_t *response) {
\r
531 if (DAP_Data.debug_port != DAP_PORT_JTAG) {
\r
532 err:*response = DAP_ERROR;
\r
536 // Device index (JTAP TAP)
\r
537 DAP_Data.jtag_dev.index = *request;
\r
538 if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err;
\r
540 // Select JTAG chain
\r
541 JTAG_IR(JTAG_IDCODE);
\r
543 // Read IDCODE register
\r
544 data = JTAG_ReadIDCode();
\r
547 *(response+0) = DAP_OK;
\r
548 *(response+1) = (uint8_t)(data >> 0);
\r
549 *(response+2) = (uint8_t)(data >> 8);
\r
550 *(response+3) = (uint8_t)(data >> 16);
\r
551 *(response+4) = (uint8_t)(data >> 24);
\r
558 // Process JTAG Abort command and prepare response
\r
559 // request: pointer to request data
\r
560 // response: pointer to response data
\r
561 // return: number of bytes in response
\r
562 #if (DAP_JTAG != 0)
\r
563 static uint32_t DAP_JTAG_Abort(uint8_t *request, uint8_t *response) {
\r
566 if (DAP_Data.debug_port != DAP_PORT_JTAG) {
\r
567 err:*response = DAP_ERROR;
\r
571 // Device index (JTAP TAP)
\r
572 DAP_Data.jtag_dev.index = *request;
\r
573 if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err;
\r
575 // Select JTAG chain
\r
576 JTAG_IR(JTAG_ABORT);
\r
579 data = (*(request+1) << 0) |
\r
580 (*(request+2) << 8) |
\r
581 (*(request+3) << 16) |
\r
582 (*(request+4) << 24);
\r
584 // Write Abort register
\r
585 JTAG_WriteAbort(data);
\r
586 *response = DAP_OK;
\r
593 // Process Transfer Configure command and prepare response
\r
594 // request: pointer to request data
\r
595 // response: pointer to response data
\r
596 // return: number of bytes in response
\r
597 static uint32_t DAP_TransferConfigure(uint8_t *request, uint8_t *response) {
\r
599 DAP_Data.transfer.idle_cycles = *(request+0);
\r
600 DAP_Data.transfer.retry_count = *(request+1) | (*(request+2) << 8);
\r
601 DAP_Data.transfer.match_retry = *(request+3) | (*(request+4) << 8);
\r
603 *response = DAP_OK;
\r
609 // Process SWD Transfer command and prepare response
\r
610 // request: pointer to request data
\r
611 // response: pointer to response data
\r
612 // return: number of bytes in response
\r
614 static uint32_t DAP_SWD_Transfer(uint8_t *request, uint8_t *response) {
\r
615 uint32_t request_count;
\r
616 uint32_t request_value;
\r
617 uint32_t response_count;
\r
618 uint32_t response_value;
\r
619 uint8_t *response_head;
\r
620 uint32_t post_read;
\r
621 uint32_t check_write;
\r
622 uint32_t match_value;
\r
623 uint32_t match_retry;
\r
627 response_count = 0;
\r
628 response_value = 0;
\r
629 response_head = response;
\r
632 DAP_TransferAbort = 0;
\r
637 request++; // Ignore DAP index
\r
639 request_count = *request++;
\r
640 while (request_count--) {
\r
641 request_value = *request++;
\r
642 if (request_value & DAP_TRANSFER_RnW) {
\r
645 // Read was posted before
\r
646 retry = DAP_Data.transfer.retry_count;
\r
647 if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) {
\r
648 // Read previous AP data and post next AP read
\r
650 response_value = SWD_Transfer(request_value, &data);
\r
651 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
653 // Read previous AP data
\r
655 response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
\r
656 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
659 if (response_value != DAP_TRANSFER_OK) break;
\r
660 // Store previous AP data
\r
661 *response++ = (uint8_t) data;
\r
662 *response++ = (uint8_t)(data >> 8);
\r
663 *response++ = (uint8_t)(data >> 16);
\r
664 *response++ = (uint8_t)(data >> 24);
\r
666 if (request_value & DAP_TRANSFER_MATCH_VALUE) {
\r
667 // Read with value match
\r
668 match_value = (*(request+0) << 0) |
\r
669 (*(request+1) << 8) |
\r
670 (*(request+2) << 16) |
\r
671 (*(request+3) << 24);
\r
673 match_retry = DAP_Data.transfer.match_retry;
\r
674 if (request_value & DAP_TRANSFER_APnDP) {
\r
676 retry = DAP_Data.transfer.retry_count;
\r
678 response_value = SWD_Transfer(request_value, NULL);
\r
679 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
680 if (response_value != DAP_TRANSFER_OK) break;
\r
683 // Read register until its value matches or retry counter expires
\r
684 retry = DAP_Data.transfer.retry_count;
\r
686 response_value = SWD_Transfer(request_value, &data);
\r
687 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
688 if (response_value != DAP_TRANSFER_OK) break;
\r
689 } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort);
\r
690 if ((data & DAP_Data.transfer.match_mask) != match_value) {
\r
691 response_value |= DAP_TRANSFER_MISMATCH;
\r
693 if (response_value != DAP_TRANSFER_OK) break;
\r
696 retry = DAP_Data.transfer.retry_count;
\r
697 if (request_value & DAP_TRANSFER_APnDP) {
\r
698 // Read AP register
\r
699 if (post_read == 0) {
\r
702 response_value = SWD_Transfer(request_value, NULL);
\r
703 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
704 if (response_value != DAP_TRANSFER_OK) break;
\r
708 // Read DP register
\r
710 response_value = SWD_Transfer(request_value, &data);
\r
711 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
712 if (response_value != DAP_TRANSFER_OK) break;
\r
714 *response++ = (uint8_t) data;
\r
715 *response++ = (uint8_t)(data >> 8);
\r
716 *response++ = (uint8_t)(data >> 16);
\r
717 *response++ = (uint8_t)(data >> 24);
\r
724 // Read previous data
\r
725 retry = DAP_Data.transfer.retry_count;
\r
727 response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
\r
728 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
729 if (response_value != DAP_TRANSFER_OK) break;
\r
730 // Store previous data
\r
731 *response++ = (uint8_t) data;
\r
732 *response++ = (uint8_t)(data >> 8);
\r
733 *response++ = (uint8_t)(data >> 16);
\r
734 *response++ = (uint8_t)(data >> 24);
\r
738 data = (*(request+0) << 0) |
\r
739 (*(request+1) << 8) |
\r
740 (*(request+2) << 16) |
\r
741 (*(request+3) << 24);
\r
743 if (request_value & DAP_TRANSFER_MATCH_MASK) {
\r
744 // Write match mask
\r
745 DAP_Data.transfer.match_mask = data;
\r
746 response_value = DAP_TRANSFER_OK;
\r
748 // Write DP/AP register
\r
749 retry = DAP_Data.transfer.retry_count;
\r
751 response_value = SWD_Transfer(request_value, &data);
\r
752 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
753 if (response_value != DAP_TRANSFER_OK) break;
\r
758 if (DAP_TransferAbort) break;
\r
761 if (response_value == DAP_TRANSFER_OK) {
\r
763 // Read previous data
\r
764 retry = DAP_Data.transfer.retry_count;
\r
766 response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
\r
767 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
768 if (response_value != DAP_TRANSFER_OK) goto end;
\r
769 // Store previous data
\r
770 *response++ = (uint8_t) data;
\r
771 *response++ = (uint8_t)(data >> 8);
\r
772 *response++ = (uint8_t)(data >> 16);
\r
773 *response++ = (uint8_t)(data >> 24);
\r
774 } else if (check_write) {
\r
775 // Check last write
\r
776 retry = DAP_Data.transfer.retry_count;
\r
778 response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
\r
779 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
784 *(response_head+0) = (uint8_t)response_count;
\r
785 *(response_head+1) = (uint8_t)response_value;
\r
787 return (response - response_head);
\r
792 // Process JTAG Transfer command and prepare response
\r
793 // request: pointer to request data
\r
794 // response: pointer to response data
\r
795 // return: number of bytes in response
\r
796 #if (DAP_JTAG != 0)
\r
797 static uint32_t DAP_JTAG_Transfer(uint8_t *request, uint8_t *response) {
\r
798 uint32_t request_count;
\r
799 uint32_t request_value;
\r
800 uint32_t request_ir;
\r
801 uint32_t response_count;
\r
802 uint32_t response_value;
\r
803 uint8_t *response_head;
\r
804 uint32_t post_read;
\r
805 uint32_t match_value;
\r
806 uint32_t match_retry;
\r
811 response_count = 0;
\r
812 response_value = 0;
\r
813 response_head = response;
\r
816 DAP_TransferAbort = 0;
\r
821 // Device index (JTAP TAP)
\r
822 DAP_Data.jtag_dev.index = *request++;
\r
823 if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end;
\r
825 request_count = *request++;
\r
826 while (request_count--) {
\r
827 request_value = *request++;
\r
828 request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC;
\r
829 if (request_value & DAP_TRANSFER_RnW) {
\r
832 // Read was posted before
\r
833 retry = DAP_Data.transfer.retry_count;
\r
834 if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == 0)) {
\r
835 // Read previous data and post next read
\r
837 response_value = JTAG_Transfer(request_value, &data);
\r
838 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
840 // Select JTAG chain
\r
841 if (ir != JTAG_DPACC) {
\r
845 // Read previous data
\r
847 response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
\r
848 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
851 if (response_value != DAP_TRANSFER_OK) break;
\r
852 // Store previous data
\r
853 *response++ = (uint8_t) data;
\r
854 *response++ = (uint8_t)(data >> 8);
\r
855 *response++ = (uint8_t)(data >> 16);
\r
856 *response++ = (uint8_t)(data >> 24);
\r
858 if (request_value & DAP_TRANSFER_MATCH_VALUE) {
\r
859 // Read with value match
\r
860 match_value = (*(request+0) << 0) |
\r
861 (*(request+1) << 8) |
\r
862 (*(request+2) << 16) |
\r
863 (*(request+3) << 24);
\r
865 match_retry = DAP_Data.transfer.match_retry;
\r
866 // Select JTAG chain
\r
867 if (ir != request_ir) {
\r
872 retry = DAP_Data.transfer.retry_count;
\r
874 response_value = JTAG_Transfer(request_value, NULL);
\r
875 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
876 if (response_value != DAP_TRANSFER_OK) break;
\r
878 // Read register until its value matches or retry counter expires
\r
879 retry = DAP_Data.transfer.retry_count;
\r
881 response_value = JTAG_Transfer(request_value, &data);
\r
882 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
883 if (response_value != DAP_TRANSFER_OK) break;
\r
884 } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort);
\r
885 if ((data & DAP_Data.transfer.match_mask) != match_value) {
\r
886 response_value |= DAP_TRANSFER_MISMATCH;
\r
888 if (response_value != DAP_TRANSFER_OK) break;
\r
891 if (post_read == 0) {
\r
892 // Select JTAG chain
\r
893 if (ir != request_ir) {
\r
898 retry = DAP_Data.transfer.retry_count;
\r
900 response_value = JTAG_Transfer(request_value, NULL);
\r
901 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
902 if (response_value != DAP_TRANSFER_OK) break;
\r
909 // Select JTAG chain
\r
910 if (ir != JTAG_DPACC) {
\r
914 // Read previous data
\r
915 retry = DAP_Data.transfer.retry_count;
\r
917 response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
\r
918 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
919 if (response_value != DAP_TRANSFER_OK) break;
\r
920 // Store previous data
\r
921 *response++ = (uint8_t) data;
\r
922 *response++ = (uint8_t)(data >> 8);
\r
923 *response++ = (uint8_t)(data >> 16);
\r
924 *response++ = (uint8_t)(data >> 24);
\r
928 data = (*(request+0) << 0) |
\r
929 (*(request+1) << 8) |
\r
930 (*(request+2) << 16) |
\r
931 (*(request+3) << 24);
\r
933 if (request_value & DAP_TRANSFER_MATCH_MASK) {
\r
934 // Write match mask
\r
935 DAP_Data.transfer.match_mask = data;
\r
936 response_value = DAP_TRANSFER_OK;
\r
938 // Select JTAG chain
\r
939 if (ir != request_ir) {
\r
943 // Write DP/AP register
\r
944 retry = DAP_Data.transfer.retry_count;
\r
946 response_value = JTAG_Transfer(request_value, &data);
\r
947 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
948 if (response_value != DAP_TRANSFER_OK) break;
\r
952 if (DAP_TransferAbort) break;
\r
955 if (response_value == DAP_TRANSFER_OK) {
\r
956 // Select JTAG chain
\r
957 if (ir != JTAG_DPACC) {
\r
962 // Read previous data
\r
963 retry = DAP_Data.transfer.retry_count;
\r
965 response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
\r
966 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
967 if (response_value != DAP_TRANSFER_OK) goto end;
\r
968 // Store previous data
\r
969 *response++ = (uint8_t) data;
\r
970 *response++ = (uint8_t)(data >> 8);
\r
971 *response++ = (uint8_t)(data >> 16);
\r
972 *response++ = (uint8_t)(data >> 24);
\r
974 // Check last write
\r
975 retry = DAP_Data.transfer.retry_count;
\r
977 response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
\r
978 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
983 *(response_head+0) = (uint8_t)response_count;
\r
984 *(response_head+1) = (uint8_t)response_value;
\r
986 return (response - response_head);
\r
991 // Process SWD Transfer Block command and prepare response
\r
992 // request: pointer to request data
\r
993 // response: pointer to response data
\r
994 // return: number of bytes in response
\r
996 static uint32_t DAP_SWD_TransferBlock(uint8_t *request, uint8_t *response) {
\r
997 uint32_t request_count;
\r
998 uint32_t request_value;
\r
999 uint32_t response_count;
\r
1000 uint32_t response_value;
\r
1001 uint8_t *response_head;
\r
1005 response_count = 0;
\r
1006 response_value = 0;
\r
1007 response_head = response;
\r
1010 DAP_TransferAbort = 0;
\r
1012 request++; // Ignore DAP index
\r
1014 request_count = *request | (*(request+1) << 8);
\r
1016 if (request_count == 0) goto end;
\r
1018 request_value = *request++;
\r
1019 if (request_value & DAP_TRANSFER_RnW) {
\r
1020 // Read register block
\r
1021 if (request_value & DAP_TRANSFER_APnDP) {
\r
1023 retry = DAP_Data.transfer.retry_count;
\r
1025 response_value = SWD_Transfer(request_value, NULL);
\r
1026 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1027 if (response_value != DAP_TRANSFER_OK) goto end;
\r
1029 while (request_count--) {
\r
1030 // Read DP/AP register
\r
1031 if ((request_count == 0) && (request_value & DAP_TRANSFER_APnDP)) {
\r
1033 request_value = DP_RDBUFF | DAP_TRANSFER_RnW;
\r
1035 retry = DAP_Data.transfer.retry_count;
\r
1037 response_value = SWD_Transfer(request_value, &data);
\r
1038 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1039 if (response_value != DAP_TRANSFER_OK) goto end;
\r
1041 *response++ = (uint8_t) data;
\r
1042 *response++ = (uint8_t)(data >> 8);
\r
1043 *response++ = (uint8_t)(data >> 16);
\r
1044 *response++ = (uint8_t)(data >> 24);
\r
1048 // Write register block
\r
1049 while (request_count--) {
\r
1051 data = (*(request+0) << 0) |
\r
1052 (*(request+1) << 8) |
\r
1053 (*(request+2) << 16) |
\r
1054 (*(request+3) << 24);
\r
1056 // Write DP/AP register
\r
1057 retry = DAP_Data.transfer.retry_count;
\r
1059 response_value = SWD_Transfer(request_value, &data);
\r
1060 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1061 if (response_value != DAP_TRANSFER_OK) goto end;
\r
1064 // Check last write
\r
1065 retry = DAP_Data.transfer.retry_count;
\r
1067 response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
\r
1068 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1072 *(response_head+0) = (uint8_t)(response_count >> 0);
\r
1073 *(response_head+1) = (uint8_t)(response_count >> 8);
\r
1074 *(response_head+2) = (uint8_t) response_value;
\r
1076 return (response - response_head);
\r
1081 // Process JTAG Transfer Block command and prepare response
\r
1082 // request: pointer to request data
\r
1083 // response: pointer to response data
\r
1084 // return: number of bytes in response
\r
1085 #if (DAP_JTAG != 0)
\r
1086 static uint32_t DAP_JTAG_TransferBlock(uint8_t *request, uint8_t *response) {
\r
1087 uint32_t request_count;
\r
1088 uint32_t request_value;
\r
1089 uint32_t response_count;
\r
1090 uint32_t response_value;
\r
1091 uint8_t *response_head;
\r
1096 response_count = 0;
\r
1097 response_value = 0;
\r
1098 response_head = response;
\r
1101 DAP_TransferAbort = 0;
\r
1103 // Device index (JTAP TAP)
\r
1104 DAP_Data.jtag_dev.index = *request++;
\r
1105 if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end;
\r
1107 request_count = *request | (*(request+1) << 8);
\r
1109 if (request_count == 0) goto end;
\r
1111 request_value = *request++;
\r
1113 // Select JTAG chain
\r
1114 ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC;
\r
1117 if (request_value & DAP_TRANSFER_RnW) {
\r
1119 retry = DAP_Data.transfer.retry_count;
\r
1121 response_value = JTAG_Transfer(request_value, NULL);
\r
1122 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1123 if (response_value != DAP_TRANSFER_OK) goto end;
\r
1124 // Read register block
\r
1125 while (request_count--) {
\r
1126 // Read DP/AP register
\r
1127 if (request_count == 0) {
\r
1129 if (ir != JTAG_DPACC) {
\r
1130 JTAG_IR(JTAG_DPACC);
\r
1132 request_value = DP_RDBUFF | DAP_TRANSFER_RnW;
\r
1134 retry = DAP_Data.transfer.retry_count;
\r
1136 response_value = JTAG_Transfer(request_value, &data);
\r
1137 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1138 if (response_value != DAP_TRANSFER_OK) goto end;
\r
1140 *response++ = (uint8_t) data;
\r
1141 *response++ = (uint8_t)(data >> 8);
\r
1142 *response++ = (uint8_t)(data >> 16);
\r
1143 *response++ = (uint8_t)(data >> 24);
\r
1147 // Write register block
\r
1148 while (request_count--) {
\r
1150 data = (*(request+0) << 0) |
\r
1151 (*(request+1) << 8) |
\r
1152 (*(request+2) << 16) |
\r
1153 (*(request+3) << 24);
\r
1155 // Write DP/AP register
\r
1156 retry = DAP_Data.transfer.retry_count;
\r
1158 response_value = JTAG_Transfer(request_value, &data);
\r
1159 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1160 if (response_value != DAP_TRANSFER_OK) goto end;
\r
1163 // Check last write
\r
1164 if (ir != JTAG_DPACC) {
\r
1165 JTAG_IR(JTAG_DPACC);
\r
1167 retry = DAP_Data.transfer.retry_count;
\r
1169 response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
\r
1170 } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
\r
1174 *(response_head+0) = (uint8_t)(response_count >> 0);
\r
1175 *(response_head+1) = (uint8_t)(response_count >> 8);
\r
1176 *(response_head+2) = (uint8_t) response_value;
\r
1178 return (response - response_head);
\r
1183 // Process DAP Vendor command and prepare response
\r
1184 // Default function (can be overridden)
\r
1185 // request: pointer to request data
\r
1186 // response: pointer to response data
\r
1187 // return: number of bytes in response
\r
1188 __weak uint32_t DAP_ProcessVendorCommand(uint8_t *request, uint8_t *response) {
\r
1189 *response = ID_DAP_Invalid;
\r
1194 // Process DAP command and prepare response
\r
1195 // request: pointer to request data
\r
1196 // response: pointer to response data
\r
1197 // return: number of bytes in response
\r
1198 uint32_t DAP_ProcessCommand(uint8_t *request, uint8_t *response) {
\r
1201 if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) {
\r
1202 return DAP_ProcessVendorCommand(request, response);
\r
1205 *response++ = *request;
\r
1207 switch (*request++) {
\r
1209 num = DAP_Info(*request, response+1);
\r
1213 num = DAP_LED(request, response);
\r
1215 case ID_DAP_Connect:
\r
1216 num = DAP_Connect(request, response);
\r
1218 case ID_DAP_Disconnect:
\r
1219 num = DAP_Disconnect(response);
\r
1221 case ID_DAP_Delay:
\r
1222 num = DAP_Delay(request, response);
\r
1224 case ID_DAP_ResetTarget:
\r
1225 num = DAP_ResetTarget(response);
\r
1228 #if ((DAP_SWD != 0) || (DAP_JTAG != 0))
\r
1229 case ID_DAP_SWJ_Pins:
\r
1230 num = DAP_SWJ_Pins(request, response);
\r
1232 case ID_DAP_SWJ_Clock:
\r
1233 num = DAP_SWJ_Clock(request, response);
\r
1235 case ID_DAP_SWJ_Sequence:
\r
1236 num = DAP_SWJ_Sequence(request, response);
\r
1239 case ID_DAP_SWJ_Pins:
\r
1240 case ID_DAP_SWJ_Clock:
\r
1241 case ID_DAP_SWJ_Sequence:
\r
1242 *response = DAP_ERROR;
\r
1246 #if (DAP_SWD != 0)
\r
1247 case ID_DAP_SWD_Configure:
\r
1248 num = DAP_SWD_Configure(request, response);
\r
1251 case ID_DAP_SWD_Configure:
\r
1252 *response = DAP_ERROR;
\r
1256 #if (DAP_JTAG != 0)
\r
1257 case ID_DAP_JTAG_Sequence:
\r
1258 num = DAP_JTAG_Sequence(request, response);
\r
1260 case ID_DAP_JTAG_Configure:
\r
1261 num = DAP_JTAG_Configure(request, response);
\r
1263 case ID_DAP_JTAG_IDCODE:
\r
1264 num = DAP_JTAG_IDCode(request, response);
\r
1267 case ID_DAP_JTAG_Sequence:
\r
1268 case ID_DAP_JTAG_Configure:
\r
1269 case ID_DAP_JTAG_IDCODE:
\r
1270 *response = DAP_ERROR;
\r
1274 case ID_DAP_TransferConfigure:
\r
1275 num = DAP_TransferConfigure(request, response);
\r
1278 case ID_DAP_Transfer:
\r
1279 switch (DAP_Data.debug_port) {
\r
1280 #if (DAP_SWD != 0)
\r
1281 case DAP_PORT_SWD:
\r
1282 num = DAP_SWD_Transfer (request, response);
\r
1285 #if (DAP_JTAG != 0)
\r
1286 case DAP_PORT_JTAG:
\r
1287 num = DAP_JTAG_Transfer(request, response);
\r
1291 *(response+0) = 0; // Response count
\r
1292 *(response+1) = 0; // Response value
\r
1297 case ID_DAP_TransferBlock:
\r
1298 switch (DAP_Data.debug_port) {
\r
1299 #if (DAP_SWD != 0)
\r
1300 case DAP_PORT_SWD:
\r
1301 num = DAP_SWD_TransferBlock (request, response);
\r
1304 #if (DAP_JTAG != 0)
\r
1305 case DAP_PORT_JTAG:
\r
1306 num = DAP_JTAG_TransferBlock(request, response);
\r
1310 *(response+0) = 0; // Response count [7:0]
\r
1311 *(response+1) = 0; // Response count[15:8]
\r
1312 *(response+2) = 0; // Response value
\r
1317 case ID_DAP_WriteABORT:
\r
1318 switch (DAP_Data.debug_port) {
\r
1319 #if (DAP_SWD != 0)
\r
1320 case DAP_PORT_SWD:
\r
1321 num = DAP_SWD_Abort (request, response);
\r
1324 #if (DAP_JTAG != 0)
\r
1325 case DAP_PORT_JTAG:
\r
1326 num = DAP_JTAG_Abort(request, response);
\r
1330 *response = DAP_ERROR;
\r
1336 *(response-1) = ID_DAP_Invalid;
\r
1345 void DAP_Setup(void) {
\r
1347 // Default settings (only non-zero values)
\r
1348 //DAP_Data.debug_port = 0;
\r
1349 //DAP_Data.fast_clock = 0;
\r
1350 DAP_Data.clock_delay = CLOCK_DELAY(DAP_DEFAULT_SWJ_CLOCK);
\r
1351 //DAP_Data.transfer.idle_cycles = 0;
\r
1352 DAP_Data.transfer.retry_count = 100;
\r
1353 //DAP_Data.transfer.match_retry = 0;
\r
1354 //DAP_Data.transfer.match_mask = 0x000000;
\r
1355 #if (DAP_SWD != 0)
\r
1356 DAP_Data.swd_conf.turnaround = 1;
\r
1357 //DAP_Data.swd_conf.data_phase = 0;
\r
1359 #if (DAP_JTAG != 0)
\r
1360 //DAP_Data.jtag_dev.count = 0;
\r
1363 DAP_SETUP(); // Device specific setup
\r