1 /*
2 * Copyright (c) 2018-2019 PHYTEC Messtechnik GmbH
3 * Copyright (c) 2023 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /*
9 * This file is based on DAP.c from CMSIS-DAP Source (Revision: V2.0.0)
10 * https://github.com/ARM-software/CMSIS_5/tree/develop/CMSIS/DAP/Firmware
11 * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
12 * SPDX-License-Identifier: Apache-2.0
13 */
14
15 #include <string.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/device.h>
18 #include <zephyr/init.h>
19 #include <zephyr/sys/byteorder.h>
20 #include <zephyr/drivers/swdp.h>
21 #include <stdint.h>
22
23 #include <cmsis_dap.h>
24
25 #include <zephyr/logging/log.h>
26 LOG_MODULE_REGISTER(dap, CONFIG_DAP_LOG_LEVEL);
27
28 #define DAP_STATE_CONNECTED 0
29
30 struct dap_context {
31 struct device *swdp_dev;
32 atomic_t state;
33 uint8_t debug_port;
34 uint8_t capabilities;
35 uint16_t pkt_size;
36 struct {
37 /* Idle cycles after transfer */
38 uint8_t idle_cycles;
39 /* Number of retries after WAIT response */
40 uint16_t retry_count;
41 /* Number of retries if read value does not match */
42 uint16_t match_retry;
43 /* Match Mask */
44 uint32_t match_mask;
45 } transfer;
46 };
47
48 static struct dap_context dap_ctx[1];
49
50 #define CMSIS_DAP_PACKET_MIN_SIZE 64
51
52 BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_PROBE_VENDOR) <=
53 MIN(CMSIS_DAP_PACKET_MIN_SIZE - 2, UINT8_MAX - 2),
54 "PROBE_VENDOR string is too long.");
55 BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_PROBE_NAME) <=
56 MIN(CMSIS_DAP_PACKET_MIN_SIZE - 2, UINT8_MAX - 2),
57 "PROBE_NAME string is too long.");
58 BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_BOARD_VENDOR) <=
59 MIN(CMSIS_DAP_PACKET_MIN_SIZE - 2, UINT8_MAX - 2),
60 "BOARD_VENDOR string is too long.");
61 BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_BOARD_NAME) <=
62 MIN(CMSIS_DAP_PACKET_MIN_SIZE - 2, UINT8_MAX - 2),
63 "BOARD_NAME string is too long.");
64 BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_DEVICE_VENDOR) <=
65 MIN(CMSIS_DAP_PACKET_MIN_SIZE - 2, UINT8_MAX - 2),
66 "DEVICE_VENDOR string is too long.");
67 BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_DEVICE_NAME) <=
68 MIN(CMSIS_DAP_PACKET_MIN_SIZE - 2, UINT8_MAX - 2),
69 "DEVICE_NAME string is too long.");
70
71 /* Get DAP Information */
dap_info(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)72 static uint16_t dap_info(struct dap_context *const ctx,
73 const uint8_t *const request,
74 uint8_t *const response)
75 {
76 uint8_t *info = response + 1;
77 uint8_t id = request[0];
78 uint8_t length = 0U;
79
80 switch (id) {
81 case DAP_ID_VENDOR:
82 LOG_DBG("ID_VENDOR");
83 memcpy(info, CONFIG_CMSIS_DAP_PROBE_VENDOR,
84 sizeof(CONFIG_CMSIS_DAP_PROBE_VENDOR));
85 length = sizeof(CONFIG_CMSIS_DAP_PROBE_VENDOR);
86 break;
87 case DAP_ID_PRODUCT:
88 LOG_DBG("ID_PRODUCT");
89 memcpy(info, CONFIG_CMSIS_DAP_PROBE_NAME,
90 sizeof(CONFIG_CMSIS_DAP_PROBE_NAME));
91 length = sizeof(CONFIG_CMSIS_DAP_PROBE_NAME);
92 break;
93 case DAP_ID_SER_NUM:
94 /* optional to implement */
95 LOG_DBG("ID_SER_NUM unsupported");
96 break;
97 case DAP_ID_FW_VER:
98 LOG_DBG("ID_FW_VER");
99 memcpy(info, DAP_FW_VER, sizeof(DAP_FW_VER));
100 length = sizeof(DAP_FW_VER);
101 break;
102 case DAP_ID_DEVICE_VENDOR:
103 LOG_DBG("ID_DEVICE_VENDOR");
104 memcpy(info, CONFIG_CMSIS_DAP_DEVICE_VENDOR,
105 sizeof(CONFIG_CMSIS_DAP_DEVICE_VENDOR));
106 length = sizeof(CONFIG_CMSIS_DAP_DEVICE_VENDOR);
107 break;
108 case DAP_ID_DEVICE_NAME:
109 LOG_DBG("ID_DEVICE_NAME");
110 memcpy(info, CONFIG_CMSIS_DAP_DEVICE_NAME,
111 sizeof(CONFIG_CMSIS_DAP_DEVICE_NAME));
112 length = sizeof(CONFIG_CMSIS_DAP_DEVICE_NAME);
113 break;
114 case DAP_ID_BOARD_VENDOR:
115 LOG_DBG("ID_BOARD_VENDOR");
116 memcpy(info, CONFIG_CMSIS_DAP_BOARD_VENDOR,
117 sizeof(CONFIG_CMSIS_DAP_BOARD_VENDOR));
118 length = sizeof(CONFIG_CMSIS_DAP_BOARD_VENDOR);
119 break;
120 case DAP_ID_BOARD_NAME:
121 memcpy(info, CONFIG_CMSIS_DAP_BOARD_NAME,
122 sizeof(CONFIG_CMSIS_DAP_BOARD_NAME));
123 length = sizeof(CONFIG_CMSIS_DAP_BOARD_NAME);
124 LOG_DBG("ID_BOARD_NAME");
125 break;
126 case DAP_ID_PRODUCT_FW_VER:
127 /* optional to implement */
128 LOG_DBG("ID_PRODUCT_FW_VER unsupported");
129 break;
130 case DAP_ID_CAPABILITIES:
131 info[0] = ctx->capabilities;
132 LOG_DBG("ID_CAPABILITIES 0x%0x", info[0]);
133 length = 1U;
134 break;
135 case DAP_ID_TIMESTAMP_CLOCK:
136 LOG_DBG("ID_TIMESTAMP_CLOCK unsupported");
137 break;
138 case DAP_ID_UART_RX_BUFFER_SIZE:
139 LOG_DBG("ID_UART_RX_BUFFER_SIZE unsupported");
140 break;
141 case DAP_ID_UART_TX_BUFFER_SIZE:
142 LOG_DBG("ID_UART_TX_BUFFER_SIZE unsupported");
143 break;
144 case DAP_ID_SWO_BUFFER_SIZE:
145 LOG_DBG("ID_SWO_BUFFER_SIZE unsupported");
146 break;
147 case DAP_ID_PACKET_SIZE:
148 LOG_DBG("ID_PACKET_SIZE");
149 sys_put_le16(ctx->pkt_size, &info[0]);
150 length = 2U;
151 break;
152 case DAP_ID_PACKET_COUNT:
153 LOG_DBG("ID_PACKET_COUNT");
154 info[0] = CONFIG_CMSIS_DAP_PACKET_COUNT;
155 length = 1U;
156 break;
157 default:
158 LOG_DBG("unsupported ID");
159 break;
160 }
161
162 response[0] = length;
163
164 return length + 1U;
165 }
166
167 /* Process Host Status command and prepare response */
dap_host_status(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)168 static uint16_t dap_host_status(struct dap_context *const ctx,
169 const uint8_t *const request,
170 uint8_t *const response)
171 {
172 switch (request[0]) {
173 case DAP_DEBUGGER_CONNECTED:
174 if (request[1]) {
175 LOG_INF("Debugger connected");
176 } else {
177 LOG_INF("Debugger disconnected");
178 }
179 break;
180 case DAP_TARGET_RUNNING:
181 LOG_DBG("unsupported");
182 break;
183 default:
184 *response = DAP_ERROR;
185 return 1U;
186 }
187
188 response[0] = DAP_OK;
189 return 1U;
190 }
191
192 /* Process Connect command and prepare response */
dap_connect(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)193 static uint16_t dap_connect(struct dap_context *const ctx,
194 const uint8_t *const request,
195 uint8_t *const response)
196 {
197 const struct swdp_api *api = ctx->swdp_dev->api;
198 uint8_t port;
199
200 if (request[0] == DAP_PORT_AUTODETECT) {
201 port = DAP_PORT_SWD;
202 } else {
203 port = request[0];
204 }
205
206 switch (port) {
207 case DAP_PORT_SWD:
208 LOG_INF("port swd");
209 ctx->debug_port = DAP_PORT_SWD;
210
211 if (atomic_test_and_set_bit(&ctx->state,
212 DAP_STATE_CONNECTED)) {
213 LOG_ERR("DAP device is already connected");
214 break;
215 }
216
217 api->swdp_port_on(ctx->swdp_dev);
218 break;
219 case DAP_PORT_JTAG:
220 LOG_ERR("port unsupported");
221 port = DAP_ERROR;
222 break;
223 default:
224 LOG_DBG("port disabled");
225 port = DAP_PORT_DISABLED;
226 break;
227 }
228
229 response[0] = port;
230 return 1U;
231 }
232
233 /* Process Disconnect command and prepare response */
dap_disconnect(struct dap_context * const ctx,uint8_t * const response)234 static uint16_t dap_disconnect(struct dap_context *const ctx,
235 uint8_t *const response)
236 {
237 const struct swdp_api *api = ctx->swdp_dev->api;
238
239 LOG_DBG("");
240
241 ctx->debug_port = DAP_PORT_DISABLED;
242
243 if (atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
244 api->swdp_port_off(ctx->swdp_dev);
245 } else {
246 LOG_WRN("DAP device is not connected");
247 }
248
249 response[0] = DAP_OK;
250 atomic_clear_bit(&ctx->state, DAP_STATE_CONNECTED);
251
252 return 1;
253 }
254
255 /* Process Delay command and prepare response */
dap_delay(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)256 static uint16_t dap_delay(struct dap_context *const ctx,
257 const uint8_t *const request,
258 uint8_t *const response)
259 {
260 uint16_t delay = sys_get_le16(&request[0]);
261
262 LOG_DBG("dap delay %u ms", delay);
263
264 k_busy_wait(delay * USEC_PER_MSEC);
265 response[0] = DAP_OK;
266
267 return 1U;
268 }
269
270 /* Process Reset Target command and prepare response */
dap_reset_target(struct dap_context * const ctx,uint8_t * const response)271 static uint16_t dap_reset_target(struct dap_context *const ctx,
272 uint8_t *const response)
273 {
274 response[0] = DAP_OK;
275 response[1] = 0U;
276 LOG_WRN("unsupported");
277
278 return 2;
279 }
280
281 /* Process SWJ Pins command and prepare response */
dap_swj_pins(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)282 static uint16_t dap_swj_pins(struct dap_context *const ctx,
283 const uint8_t *const request,
284 uint8_t *const response)
285 {
286 const struct swdp_api *api = ctx->swdp_dev->api;
287 uint8_t value = request[0];
288 uint8_t select = request[1];
289 uint32_t wait = sys_get_le32(&request[2]);
290 k_timepoint_t end = sys_timepoint_calc(K_USEC(wait));
291 uint8_t state;
292
293 if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
294 LOG_ERR("DAP device is not connected");
295 response[0] = DAP_ERROR;
296 return 1U;
297 }
298
299 /* Skip if nothing selected. */
300 if (select) {
301 api->swdp_set_pins(ctx->swdp_dev, select, value);
302 }
303
304 do {
305 api->swdp_get_pins(ctx->swdp_dev, &state);
306 LOG_INF("select 0x%02x, value 0x%02x, wait %u, state 0x%02x",
307 select, value, wait, state);
308 if ((value & select) == (state & select)) {
309 LOG_DBG("swdp_get_pins succeeded before timeout");
310 break;
311 }
312 } while (!sys_timepoint_expired(end));
313
314 response[0] = state;
315
316 return sizeof(state);
317 }
318
319 /* Process SWJ Clock command and prepare response */
dap_swj_clock(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)320 static uint16_t dap_swj_clock(struct dap_context *const ctx,
321 const uint8_t *const request,
322 uint8_t *const response)
323 {
324 const struct swdp_api *api = ctx->swdp_dev->api;
325 uint32_t clk = sys_get_le32(&request[0]);
326
327 LOG_DBG("clock %d", clk);
328
329 if (atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
330 if (clk) {
331 api->swdp_set_clock(ctx->swdp_dev, clk);
332 response[0] = DAP_OK;
333 } else {
334 response[0] = DAP_ERROR;
335 }
336 } else {
337 LOG_WRN("DAP device is not connected");
338 response[0] = DAP_OK;
339 }
340
341 return 1U;
342 }
343
344 /* Process SWJ Sequence command and prepare response */
dap_swj_sequence(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)345 static uint16_t dap_swj_sequence(struct dap_context *const ctx,
346 const uint8_t *const request,
347 uint8_t *const response)
348 {
349 const struct swdp_api *api = ctx->swdp_dev->api;
350 uint16_t count = request[0];
351
352 LOG_DBG("count %u", count);
353
354 if (count == 0U) {
355 count = 256U;
356 }
357
358 if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
359 LOG_ERR("DAP device is not connected");
360 response[0] = DAP_ERROR;
361 return 1U;
362 }
363
364 api->swdp_output_sequence(ctx->swdp_dev, count, &request[1]);
365 response[0] = DAP_OK;
366
367 return 1U;
368 }
369
370 /* Process SWD Configure command and prepare response */
dap_swdp_configure(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)371 static uint16_t dap_swdp_configure(struct dap_context *const ctx,
372 const uint8_t *const request,
373 uint8_t *const response)
374 {
375 const struct swdp_api *api = ctx->swdp_dev->api;
376 uint8_t turnaround = (request[0] & 0x03U) + 1U;
377 bool data_phase = (request[0] & 0x04U) ? true : false;
378
379 if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
380 LOG_ERR("DAP device is not connected");
381 response[0] = DAP_ERROR;
382 return 1U;
383 }
384
385 api->swdp_configure(ctx->swdp_dev, turnaround, data_phase);
386 response[0] = DAP_OK;
387
388 return 1U;
389 }
390
391 /* Process Transfer Configure command and prepare response */
dap_transfer_cfg(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)392 static uint16_t dap_transfer_cfg(struct dap_context *const ctx,
393 const uint8_t *const request,
394 uint8_t *const response)
395 {
396
397 ctx->transfer.idle_cycles = request[0];
398 ctx->transfer.retry_count = sys_get_le16(&request[1]);
399 ctx->transfer.match_retry = sys_get_le16(&request[3]);
400 LOG_DBG("idle_cycles %d, retry_count %d, match_retry %d",
401 ctx->transfer.idle_cycles,
402 ctx->transfer.retry_count,
403 ctx->transfer.match_retry);
404
405 response[0] = DAP_OK;
406 return 1U;
407 }
408
do_swdp_transfer(struct dap_context * const ctx,const uint8_t req_val,uint32_t * data)409 static inline uint8_t do_swdp_transfer(struct dap_context *const ctx,
410 const uint8_t req_val,
411 uint32_t *data)
412 {
413 const struct swdp_api *api = ctx->swdp_dev->api;
414 uint32_t retry = ctx->transfer.retry_count;
415 uint8_t rspns_val;
416
417 do {
418 api->swdp_transfer(ctx->swdp_dev,
419 req_val,
420 data,
421 ctx->transfer.idle_cycles,
422 &rspns_val);
423 } while ((rspns_val == SWDP_ACK_WAIT) && retry--);
424
425 return rspns_val;
426 }
427
swdp_transfer_match(struct dap_context * const ctx,const uint8_t req_val,const uint32_t match_val)428 static uint8_t swdp_transfer_match(struct dap_context *const ctx,
429 const uint8_t req_val,
430 const uint32_t match_val)
431 {
432 uint32_t match_retry = ctx->transfer.match_retry;
433 uint32_t data;
434 uint8_t rspns_val;
435
436 if (req_val & SWDP_REQUEST_APnDP) {
437 /* Post AP read, result will be returned on the next transfer */
438 rspns_val = do_swdp_transfer(ctx, req_val, NULL);
439 if (rspns_val != SWDP_ACK_OK) {
440 return rspns_val;
441 }
442 }
443
444 do {
445 /*
446 * Read register until its value matches
447 * or retry counter expires
448 */
449 rspns_val = do_swdp_transfer(ctx, req_val, &data);
450 if (rspns_val != SWDP_ACK_OK) {
451 return rspns_val;
452 }
453
454 } while (((data & ctx->transfer.match_mask) != match_val) &&
455 match_retry--);
456
457 if ((data & ctx->transfer.match_mask) != match_val) {
458 rspns_val |= DAP_TRANSFER_MISMATCH;
459 }
460
461 return rspns_val;
462 }
463
464 /*
465 * Process SWD Transfer command and prepare response
466 * pyOCD counterpart is _encode_transfer_data.
467 * Packet format: one byte DAP_index (ignored)
468 * one bytes transfer_count
469 * following by number transfer_count pairs of
470 * one byte request (register)
471 * four byte data (for write request only)
472 */
dap_swdp_transfer(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)473 static uint16_t dap_swdp_transfer(struct dap_context *const ctx,
474 const uint8_t *const request,
475 uint8_t *const response)
476 {
477 uint8_t *rspns_buf;
478 const uint8_t *req_buf;
479 uint8_t rspns_cnt = 0;
480 uint8_t rspns_val = 0;
481 bool post_read = false;
482 uint32_t check_write = 0;
483 uint8_t req_cnt;
484 uint8_t req_val;
485 uint32_t match_val;
486 uint32_t data;
487
488 /* Ignore DAP index request[0] */
489 req_cnt = request[1];
490 req_buf = request + sizeof(req_cnt) + 1;
491 rspns_buf = response + (sizeof(rspns_cnt) + sizeof(rspns_val));
492
493 for (; req_cnt; req_cnt--) {
494 req_val = *req_buf++;
495 if (req_val & SWDP_REQUEST_RnW) {
496 /* Read register */
497 if (post_read) {
498 /*
499 * Read was posted before, read previous AP
500 * data or post next AP read.
501 */
502 if ((req_val & (SWDP_REQUEST_APnDP |
503 DAP_TRANSFER_MATCH_VALUE)) !=
504 SWDP_REQUEST_APnDP) {
505 req_val = DP_RDBUFF | SWDP_REQUEST_RnW;
506 post_read = false;
507 }
508
509 rspns_val = do_swdp_transfer(ctx, req_val, &data);
510 if (rspns_val != SWDP_ACK_OK) {
511 break;
512 }
513
514 /* Store previous AP data */
515 sys_put_le32(data, rspns_buf);
516 rspns_buf += sizeof(data);
517 }
518 if (req_val & DAP_TRANSFER_MATCH_VALUE) {
519 LOG_INF("match value read");
520 /* Read with value match */
521 match_val = sys_get_le32(req_buf);
522 req_buf += sizeof(match_val);
523
524 rspns_val = swdp_transfer_match(ctx, req_val, match_val);
525 if (rspns_val != SWDP_ACK_OK) {
526 break;
527 }
528
529 } else if (req_val & SWDP_REQUEST_APnDP) {
530 /* Normal read */
531 if (!post_read) {
532 /* Post AP read */
533 rspns_val = do_swdp_transfer(ctx, req_val, NULL);
534 if (rspns_val != SWDP_ACK_OK) {
535 break;
536 }
537 post_read = true;
538 }
539 } else {
540 /* Read DP register */
541 rspns_val = do_swdp_transfer(ctx, req_val, &data);
542 if (rspns_val != SWDP_ACK_OK) {
543 break;
544 }
545 /* Store data */
546 sys_put_le32(data, rspns_buf);
547 rspns_buf += sizeof(data);
548 }
549 check_write = 0U;
550 } else {
551 /* Write register */
552 if (post_read) {
553 /* Read previous data */
554 rspns_val = do_swdp_transfer(ctx,
555 DP_RDBUFF | SWDP_REQUEST_RnW,
556 &data);
557 if (rspns_val != SWDP_ACK_OK) {
558 break;
559 }
560
561 /* Store previous data */
562 sys_put_le32(data, rspns_buf);
563 rspns_buf += sizeof(data);
564 post_read = false;
565 }
566 /* Load data */
567 data = sys_get_le32(req_buf);
568 req_buf += sizeof(data);
569 if (req_val & DAP_TRANSFER_MATCH_MASK) {
570 /* Write match mask */
571 ctx->transfer.match_mask = data;
572 rspns_val = SWDP_ACK_OK;
573 } else {
574 /* Write DP/AP register */
575 rspns_val = do_swdp_transfer(ctx, req_val, &data);
576 if (rspns_val != SWDP_ACK_OK) {
577 break;
578 }
579
580 check_write = 1U;
581 }
582 }
583 rspns_cnt++;
584 }
585
586 if (rspns_val == SWDP_ACK_OK) {
587 if (post_read) {
588 /* Read previous data */
589 rspns_val = do_swdp_transfer(ctx,
590 DP_RDBUFF | SWDP_REQUEST_RnW,
591 &data);
592 if (rspns_val != SWDP_ACK_OK) {
593 goto end;
594 }
595
596 /* Store previous data */
597 sys_put_le32(data, rspns_buf);
598 rspns_buf += sizeof(data);
599 } else if (check_write) {
600 /* Check last write */
601 rspns_val = do_swdp_transfer(ctx,
602 DP_RDBUFF | SWDP_REQUEST_RnW,
603 NULL);
604 }
605 }
606
607 end:
608 response[0] = rspns_cnt;
609 response[1] = rspns_val;
610
611 return (rspns_buf - response);
612 }
613
614 /* Delegate DAP Transfer command */
dap_transfer(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)615 static uint16_t dap_transfer(struct dap_context *const ctx,
616 const uint8_t *const request,
617 uint8_t *const response)
618 {
619 uint16_t retval;
620
621 if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
622 LOG_ERR("DAP device is not connected");
623 response[0] = DAP_ERROR;
624 return 1U;
625 }
626
627 switch (ctx->debug_port) {
628 case DAP_PORT_SWD:
629 retval = dap_swdp_transfer(ctx, request, response);
630 break;
631 case DAP_PORT_JTAG:
632 default:
633 LOG_ERR("port unsupported");
634 response[0] = DAP_ERROR;
635 retval = 1U;
636 }
637
638 return retval;
639 }
640
dap_swdp_sequence(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)641 static uint16_t dap_swdp_sequence(struct dap_context *const ctx,
642 const uint8_t *const request,
643 uint8_t *const response)
644 {
645 const struct swdp_api *api = ctx->swdp_dev->api;
646 const uint8_t *request_data = request + 1;
647 uint8_t *response_data = response + 1;
648 uint8_t count = request[0];
649 uint8_t num_cycles;
650 uint32_t num_bytes;
651 bool input;
652
653 switch (ctx->debug_port) {
654 case DAP_PORT_SWD:
655 response[0] = DAP_OK;
656 break;
657 case DAP_PORT_JTAG:
658 default:
659 LOG_ERR("port unsupported");
660 response[0] = DAP_ERROR;
661 return 1U;
662 }
663
664 for (size_t i = 0; i < count; ++i) {
665 input = *request_data & BIT(7);
666 num_cycles = *request_data & BIT_MASK(7);
667 num_bytes = (num_cycles + 7) >> 3; /* rounded up to full bytes */
668
669 if (num_cycles == 0) {
670 num_cycles = 64;
671 }
672
673 request_data += 1;
674
675 if (input) {
676 api->swdp_input_sequence(ctx->swdp_dev, num_cycles, response_data);
677 response_data += num_bytes;
678 } else {
679 api->swdp_output_sequence(ctx->swdp_dev, num_cycles, request_data);
680 request_data += num_bytes;
681 }
682 }
683
684 return response_data - response;
685 }
686
687 /*
688 * Process SWD DAP_TransferBlock command and prepare response.
689 * pyOCD counterpart is _encode_transfer_block_data.
690 * Packet format: one byte DAP_index (ignored)
691 * two bytes transfer_count
692 * one byte block_request (register)
693 * data[transfer_count * sizeof(uint32_t)]
694 */
dap_swdp_transferblock(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)695 static uint16_t dap_swdp_transferblock(struct dap_context *const ctx,
696 const uint8_t *const request,
697 uint8_t *const response)
698 {
699 uint32_t data;
700 uint8_t *rspns_buf;
701 const uint8_t *req_buf;
702 uint16_t rspns_cnt = 0;
703 uint16_t req_cnt;
704 uint8_t rspns_val = 0;
705 uint8_t req_val;
706
707 req_cnt = sys_get_le16(&request[1]);
708 req_val = request[3];
709 req_buf = request + (sizeof(req_cnt) + sizeof(req_val) + 1);
710 rspns_buf = response + (sizeof(rspns_cnt) + sizeof(rspns_val));
711
712 if (req_cnt == 0U) {
713 goto end;
714 }
715
716 if (req_val & SWDP_REQUEST_RnW) {
717 /* Read register block */
718 if (req_val & SWDP_REQUEST_APnDP) {
719 /* Post AP read */
720 rspns_val = do_swdp_transfer(ctx, req_val, NULL);
721 if (rspns_val != SWDP_ACK_OK) {
722 goto end;
723 }
724 }
725
726 while (req_cnt--) {
727 /* Read DP/AP register */
728 if ((req_cnt == 0U) &&
729 (req_val & SWDP_REQUEST_APnDP)) {
730 /* Last AP read */
731 req_val = DP_RDBUFF | SWDP_REQUEST_RnW;
732 }
733
734 rspns_val = do_swdp_transfer(ctx, req_val, &data);
735 if (rspns_val != SWDP_ACK_OK) {
736 goto end;
737 }
738
739 /* Store data */
740 sys_put_le32(data, rspns_buf);
741 rspns_buf += sizeof(data);
742 rspns_cnt++;
743 }
744 } else {
745 /* Write register block */
746 while (req_cnt--) {
747 /* Load data */
748 data = sys_get_le32(req_buf);
749 req_buf += sizeof(data);
750 /* Write DP/AP register */
751 rspns_val = do_swdp_transfer(ctx, req_val, &data);
752 if (rspns_val != SWDP_ACK_OK) {
753 goto end;
754 }
755
756 rspns_cnt++;
757 }
758 /* Check last write */
759 rspns_val = do_swdp_transfer(ctx, DP_RDBUFF | SWDP_REQUEST_RnW, NULL);
760 }
761
762 end:
763 sys_put_le16(rspns_cnt, &response[0]);
764 response[2] = rspns_val;
765
766 LOG_DBG("Received %u, to transmit %u, response count %u",
767 req_buf - request,
768 rspns_buf - response,
769 rspns_cnt * 4);
770
771 return (rspns_buf - response);
772 }
773
774 /* Delegate Transfer Block command */
dap_transferblock(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)775 static uint16_t dap_transferblock(struct dap_context *const ctx,
776 const uint8_t *const request,
777 uint8_t *const response)
778 {
779 uint16_t retval;
780
781 if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
782 LOG_ERR("DAP device is not connected");
783 /* Clear response count */
784 sys_put_le16(0U, &response[0]);
785 /* Clear DAP response (ACK) value */
786 response[2] = 0U;
787 return 3U;
788 }
789
790 switch (ctx->debug_port) {
791 case DAP_PORT_SWD:
792 retval = dap_swdp_transferblock(ctx, request, response);
793 break;
794 case DAP_PORT_JTAG:
795 default:
796 LOG_ERR("port unsupported");
797 /* Clear response count */
798 sys_put_le16(0U, &response[0]);
799 /* Clear DAP response (ACK) value */
800 response[2] = 0U;
801 retval = 3U;
802 }
803
804 return retval;
805 }
806
807 /* Process SWD Write ABORT command and prepare response */
dap_swdp_writeabort(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)808 static uint16_t dap_swdp_writeabort(struct dap_context *const ctx,
809 const uint8_t *const request,
810 uint8_t *const response)
811 {
812 const struct swdp_api *api = ctx->swdp_dev->api;
813 /* Load data (Ignore DAP index in request[0]) */
814 uint32_t data = sys_get_le32(&request[1]);
815
816 /* Write Abort register */
817 api->swdp_transfer(ctx->swdp_dev, DP_ABORT, &data,
818 ctx->transfer.idle_cycles, NULL);
819
820 response[0] = DAP_OK;
821 return 1U;
822 }
823
824 /* Delegate DAP Write ABORT command */
dap_writeabort(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)825 static uint16_t dap_writeabort(struct dap_context *const ctx,
826 const uint8_t *const request,
827 uint8_t *const response)
828 {
829 uint16_t retval;
830
831 if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) {
832 LOG_ERR("DAP device is not connected");
833 response[0] = DAP_ERROR;
834 return 1U;
835 }
836
837 switch (ctx->debug_port) {
838 case DAP_PORT_SWD:
839 retval = dap_swdp_writeabort(ctx, request, response);
840 break;
841 case DAP_PORT_JTAG:
842 default:
843 LOG_ERR("port unsupported");
844 response[0] = DAP_ERROR;
845 retval = 1U;
846 }
847 return retval;
848 }
849
850 /* Process DAP Vendor command request */
dap_process_vendor_cmd(struct dap_context * const ctx,const uint8_t * const request,uint8_t * const response)851 static uint16_t dap_process_vendor_cmd(struct dap_context *const ctx,
852 const uint8_t *const request,
853 uint8_t *const response)
854 {
855 response[0] = ID_DAP_INVALID;
856 return 1U;
857 }
858
859 /*
860 * Process DAP command request and prepare response
861 * request: pointer to request data
862 * response: pointer to response data
863 * return: number of bytes in response
864 *
865 * All the subsequent command functions have the same parameter
866 * and return value structure.
867 */
dap_process_cmd(struct dap_context * const ctx,const uint8_t * request,uint8_t * response)868 static uint16_t dap_process_cmd(struct dap_context *const ctx,
869 const uint8_t *request,
870 uint8_t *response)
871 {
872 uint16_t retval;
873
874 LOG_HEXDUMP_DBG(request, 8, "req");
875
876 if ((*request >= ID_DAP_VENDOR0) && (*request <= ID_DAP_VENDOR31)) {
877 return dap_process_vendor_cmd(ctx, request, response);
878 }
879
880 *response++ = *request;
881 LOG_DBG("request 0x%02x", *request);
882
883 switch (*request++) {
884 case ID_DAP_INFO:
885 retval = dap_info(ctx, request, response);
886 break;
887 case ID_DAP_HOST_STATUS:
888 retval = dap_host_status(ctx, request, response);
889 break;
890 case ID_DAP_CONNECT:
891 retval = dap_connect(ctx, request, response);
892 break;
893 case ID_DAP_DISCONNECT:
894 retval = dap_disconnect(ctx, response);
895 break;
896 case ID_DAP_DELAY:
897 retval = dap_delay(ctx, request, response);
898 break;
899 case ID_DAP_RESET_TARGET:
900 retval = dap_reset_target(ctx, response);
901 break;
902 case ID_DAP_SWJ_PINS:
903 retval = dap_swj_pins(ctx, request, response);
904 break;
905 case ID_DAP_SWJ_CLOCK:
906 retval = dap_swj_clock(ctx, request, response);
907 break;
908 case ID_DAP_SWJ_SEQUENCE:
909 retval = dap_swj_sequence(ctx, request, response);
910 break;
911 case ID_DAP_SWDP_CONFIGURE:
912 retval = dap_swdp_configure(ctx, request, response);
913 break;
914 case ID_DAP_SWDP_SEQUENCE:
915 retval = dap_swdp_sequence(ctx, request, response);
916 break;
917 case ID_DAP_JTAG_SEQUENCE:
918 LOG_ERR("JTAG sequence unsupported");
919 retval = 1;
920 *response = DAP_ERROR;
921 break;
922 case ID_DAP_JTAG_CONFIGURE:
923 LOG_ERR("JTAG configure unsupported");
924 retval = 1;
925 *response = DAP_ERROR;
926 break;
927 case ID_DAP_JTAG_IDCODE:
928 LOG_ERR("JTAG IDCODE unsupported");
929 retval = 1;
930 *response = DAP_ERROR;
931 break;
932 case ID_DAP_TRANSFER_CONFIGURE:
933 retval = dap_transfer_cfg(ctx, request, response);
934 break;
935 case ID_DAP_TRANSFER:
936 retval = dap_transfer(ctx, request, response);
937 break;
938 case ID_DAP_TRANSFER_BLOCK:
939 retval = dap_transferblock(ctx, request, response);
940 break;
941 case ID_DAP_WRITE_ABORT:
942 retval = dap_writeabort(ctx, request, response);
943 break;
944 case ID_DAP_SWO_TRANSPORT:
945 LOG_ERR("SWO Transport unsupported");
946 retval = 1;
947 *response = DAP_ERROR;
948 break;
949 case ID_DAP_SWO_MODE:
950 LOG_ERR("SWO Mode unsupported");
951 retval = 1;
952 *response = DAP_ERROR;
953 break;
954 case ID_DAP_SWO_BAUDRATE:
955 LOG_ERR("SWO Baudrate unsupported");
956 retval = 1;
957 *response = DAP_ERROR;
958 break;
959 case ID_DAP_SWO_CONTROL:
960 LOG_ERR("SWO Control unsupported");
961 retval = 1;
962 *response = DAP_ERROR;
963 break;
964 case ID_DAP_SWO_STATUS:
965 LOG_ERR("SWO Status unsupported");
966 retval = 1;
967 *response = DAP_ERROR;
968 break;
969 case ID_DAP_SWO_DATA:
970 LOG_ERR("SWO Data unsupported");
971 retval = 1;
972 *response = DAP_ERROR;
973 break;
974 case ID_DAP_UART_TRANSPORT:
975 LOG_ERR("UART Transport unsupported");
976 retval = 1;
977 *response = DAP_ERROR;
978 break;
979 case ID_DAP_UART_CONFIGURE:
980 LOG_ERR("UART Configure unsupported");
981 retval = 1;
982 *response = DAP_ERROR;
983 break;
984 case ID_DAP_UART_CONTROL:
985 LOG_ERR("UART Control unsupported");
986 retval = 1;
987 *response = DAP_ERROR;
988 break;
989 case ID_DAP_UART_STATUS:
990 LOG_ERR("UART Status unsupported");
991 retval = 1;
992 *response = DAP_ERROR;
993 break;
994 case ID_DAP_UART_TRANSFER:
995 LOG_ERR("UART Transfer unsupported");
996 retval = 1;
997 *response = DAP_ERROR;
998 break;
999
1000 default:
1001 *(response - 1) = ID_DAP_INVALID;
1002 return 1U;
1003 }
1004
1005 return (1U + retval);
1006 }
1007
1008 /*
1009 * Execute DAP command (process request and prepare response)
1010 * request: pointer to request data
1011 * response: pointer to response data
1012 * return: number of bytes in response
1013 */
dap_execute_cmd(const uint8_t * request,uint8_t * response)1014 uint32_t dap_execute_cmd(const uint8_t *request,
1015 uint8_t *response)
1016 {
1017 uint32_t retval;
1018 uint16_t n;
1019 uint8_t count;
1020
1021 if (request[0] == ID_DAP_EXECUTE_COMMANDS) {
1022 /* copy command and increment */
1023 *response++ = *request++;
1024 count = request[0];
1025 request += sizeof(count);
1026 response[0] = count;
1027 response += sizeof(count);
1028 retval = sizeof(count) + 1U;
1029 LOG_WRN("(untested) ID DAP EXECUTE_COMMANDS count %u", count);
1030 while (count--) {
1031 n = dap_process_cmd(&dap_ctx[0], request, response);
1032 retval += n;
1033 request += n;
1034 response += n;
1035 }
1036 return retval;
1037 }
1038
1039 return dap_process_cmd(&dap_ctx[0], request, response);
1040 }
1041
dap_update_pkt_size(const uint16_t pkt_size)1042 void dap_update_pkt_size(const uint16_t pkt_size)
1043 {
1044 dap_ctx[0].pkt_size = pkt_size;
1045 LOG_INF("New packet size %u", dap_ctx[0].pkt_size);
1046 }
1047
dap_setup(const struct device * const dev)1048 int dap_setup(const struct device *const dev)
1049 {
1050 dap_ctx[0].swdp_dev = (void *)dev;
1051
1052 if (!device_is_ready(dap_ctx[0].swdp_dev)) {
1053 LOG_ERR("SWD driver not ready");
1054 return -ENODEV;
1055 }
1056
1057 /* Default settings */
1058 dap_ctx[0].pkt_size = CMSIS_DAP_PACKET_MIN_SIZE;
1059 dap_ctx[0].debug_port = 0U;
1060 dap_ctx[0].transfer.idle_cycles = 0U;
1061 dap_ctx[0].transfer.retry_count = 100U;
1062 dap_ctx[0].transfer.match_retry = 0U;
1063 dap_ctx[0].transfer.match_mask = 0U;
1064 dap_ctx[0].capabilities = DAP_SUPPORTS_ATOMIC_COMMANDS |
1065 DAP_DP_SUPPORTS_SWD;
1066
1067 return 0;
1068 }
1069