openocd: fix SPDX tag format for files .c
[openocd.git] / src / jtag / drivers / cmsis_dap.c
index e498ea8295496af7693ece0ec70af08929f905cc..e708d5252f62b095949f9dabf73184188564d021 100644 (file)
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *   Copyright (C) 2021 by Adrian Negreanu                                 *
  *   groleo@gmail.com                                                      *
  *                                                                         *
  *   Copyright (C) 2013 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -40,6 +29,7 @@
 
 #include <transport/transport.h>
 #include "helper/replacements.h"
+#include <jtag/adapter.h>
 #include <jtag/swd.h>
 #include <jtag/interface.h>
 #include <jtag/commands.h>
@@ -47,6 +37,7 @@
 #include <target/cortex_m.h>
 
 #include "cmsis_dap.h"
+#include "libusb_helper.h"
 
 static const struct cmsis_dap_backend *const cmsis_dap_backends[] = {
 #if BUILD_CMSIS_DAP_USB == 1
@@ -75,12 +66,9 @@ static const struct cmsis_dap_backend *const cmsis_dap_backends[] = {
 /* vid = pid = 0 marks the end of the list */
 static uint16_t cmsis_dap_vid[MAX_USB_IDS + 1] = { 0 };
 static uint16_t cmsis_dap_pid[MAX_USB_IDS + 1] = { 0 };
-static char *cmsis_dap_serial;
 static int cmsis_dap_backend = -1;
 static bool swd_mode;
 
-#define USB_TIMEOUT       1000
-
 /* CMSIS-DAP General Commands */
 #define CMD_DAP_INFO              0x00
 #define CMD_DAP_LED               0x01
@@ -102,10 +90,16 @@ static bool swd_mode;
 #define INFO_ID_PKT_SZ            0xff      /* short */
 #define INFO_ID_SWO_BUF_SZ        0xfd      /* word */
 
-#define INFO_CAPS_SWD             BIT(0)
-#define INFO_CAPS_JTAG            BIT(1)
-#define INFO_CAPS_SWO_UART        BIT(2)
-#define INFO_CAPS_SWO_MANCHESTER  BIT(3)
+#define INFO_CAPS_SWD                 BIT(0)
+#define INFO_CAPS_JTAG                BIT(1)
+#define INFO_CAPS_SWO_UART            BIT(2)
+#define INFO_CAPS_SWO_MANCHESTER      BIT(3)
+#define INFO_CAPS_ATOMIC_CMDS         BIT(4)
+#define INFO_CAPS_TEST_DOMAIN_TIMER   BIT(5)
+#define INFO_CAPS_SWO_STREAMING_TRACE BIT(6)
+#define INFO_CAPS_UART_PORT           BIT(7)
+#define INFO_CAPS_USB_COM_PORT        BIT(8)
+#define INFO_CAPS__NUM_CAPS               9
 
 /* CMD_LED */
 #define LED_ID_CONNECT            0x00
@@ -203,11 +197,16 @@ static bool swd_mode;
 /* CMSIS-DAP Vendor Commands
  * None as yet... */
 
-static const char * const info_caps_str[] = {
-       "SWD  Supported",
-       "JTAG Supported",
-       "SWO-UART Supported",
-       "SWO-MANCHESTER Supported"
+static const char * const info_caps_str[INFO_CAPS__NUM_CAPS] = {
+       "SWD supported",
+       "JTAG supported",
+       "SWO-UART supported",
+       "SWO-MANCHESTER supported",
+       "Atomic commands supported",
+       "Test domain timer supported",
+       "SWO streaming trace supported",
+       "UART communication port supported",
+       "UART via USB COM port supported",
 };
 
 struct pending_transfer_result {
@@ -269,7 +268,7 @@ static int cmsis_dap_open(void)
        const struct cmsis_dap_backend *backend = NULL;
 
        struct cmsis_dap *dap = calloc(1, sizeof(struct cmsis_dap));
-       if (dap == NULL) {
+       if (!dap) {
                LOG_ERROR("unable to allocate memory");
                return ERROR_FAIL;
        }
@@ -277,20 +276,20 @@ static int cmsis_dap_open(void)
        if (cmsis_dap_backend >= 0) {
                /* Use forced backend */
                backend = cmsis_dap_backends[cmsis_dap_backend];
-               if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, cmsis_dap_serial) != ERROR_OK)
+               if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) != ERROR_OK)
                        backend = NULL;
        } else {
                /* Try all backends */
                for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) {
                        backend = cmsis_dap_backends[i];
-                       if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, cmsis_dap_serial) == ERROR_OK)
+                       if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) == ERROR_OK)
                                break;
                        else
                                backend = NULL;
                }
        }
 
-       if (backend == NULL) {
+       if (!backend) {
                LOG_ERROR("unable to find a matching CMSIS-DAP device");
                free(dap);
                return ERROR_FAIL;
@@ -313,8 +312,6 @@ static void cmsis_dap_close(struct cmsis_dap *dap)
        free(cmsis_dap_handle->packet_buffer);
        free(cmsis_dap_handle);
        cmsis_dap_handle = NULL;
-       free(cmsis_dap_serial);
-       cmsis_dap_serial = NULL;
 
        for (int i = 0; i < MAX_PENDING_REQUESTS; i++) {
                free(pending_fifo[i].transfers);
@@ -351,12 +348,12 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
        }
 
        uint8_t current_cmd = cmsis_dap_handle->command[0];
-       int retval = dap->backend->write(dap, txlen, USB_TIMEOUT);
+       int retval = dap->backend->write(dap, txlen, LIBUSB_TIMEOUT_MS);
        if (retval < 0)
                return retval;
 
        /* get reply */
-       retval = dap->backend->read(dap, USB_TIMEOUT);
+       retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS);
        if (retval < 0)
                return retval;
 
@@ -817,7 +814,7 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
                }
        }
 
-       int retval = dap->backend->write(dap, idx, USB_TIMEOUT);
+       int retval = dap->backend->write(dap, idx, LIBUSB_TIMEOUT_MS);
        if (retval < 0) {
                queued_retval = retval;
                goto skip;
@@ -845,7 +842,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
 
        /* get reply */
        int retval = dap->backend->read(dap, timeout_ms);
-       if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < USB_TIMEOUT)
+       if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < LIBUSB_TIMEOUT_MS)
                return;
 
        if (retval <= 0) {
@@ -920,7 +917,7 @@ static int cmsis_dap_swd_run_queue(void)
        cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
 
        while (pending_fifo_block_count)
-               cmsis_dap_swd_read_process(cmsis_dap_handle, USB_TIMEOUT);
+               cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
 
        pending_fifo_put_idx = 0;
        pending_fifo_get_idx = 0;
@@ -944,7 +941,7 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
                cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
 
                if (pending_fifo_block_count >= cmsis_dap_handle->packet_count)
-                       cmsis_dap_swd_read_process(cmsis_dap_handle, USB_TIMEOUT);
+                       cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
        }
 
        if (queued_retval != ERROR_OK)
@@ -1016,19 +1013,17 @@ static int cmsis_dap_get_caps_info(void)
        if (retval != ERROR_OK)
                return retval;
 
-       if (data[0] == 1) {
-               uint8_t caps = data[1];
+       if (data[0] == 1 || data[0] == 2) {
+               uint16_t caps = data[1];
+               if (data[0] == 2)
+                       caps |= (uint16_t)data[2] << 8;
 
                cmsis_dap_handle->caps = caps;
 
-               if (caps & INFO_CAPS_SWD)
-                       LOG_INFO("CMSIS-DAP: %s", info_caps_str[0]);
-               if (caps & INFO_CAPS_JTAG)
-                       LOG_INFO("CMSIS-DAP: %s", info_caps_str[1]);
-               if (caps & INFO_CAPS_SWO_UART)
-                       LOG_INFO("CMSIS-DAP: %s", info_caps_str[2]);
-               if (caps & INFO_CAPS_SWO_MANCHESTER)
-                       LOG_INFO("CMSIS-DAP: %s", info_caps_str[3]);
+               for (int i = 0; i < INFO_CAPS__NUM_CAPS; ++i) {
+                       if (caps & BIT(i))
+                               LOG_INFO("CMSIS-DAP: %s", info_caps_str[i]);
+               }
        }
 
        return ERROR_OK;
@@ -1124,6 +1119,11 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
                s = swd_seq_dormant_to_swd;
                s_len = swd_seq_dormant_to_swd_len;
                break;
+       case DORMANT_TO_JTAG:
+               LOG_DEBUG("DORMANT-to-JTAG");
+               s = swd_seq_dormant_to_jtag;
+               s_len = swd_seq_dormant_to_jtag_len;
+               break;
        default:
                LOG_ERROR("Sequence %d not supported", seq);
                return ERROR_FAIL;
@@ -1135,7 +1135,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
 
        /* Atmel EDBG needs renew clock setting after SWJ_Sequence
         * otherwise default frequency is used */
-       return cmsis_dap_cmd_dap_swj_clock(jtag_get_speed_khz());
+       return cmsis_dap_cmd_dap_swj_clock(adapter_get_speed_khz());
 }
 
 static int cmsis_dap_swd_open(void)
@@ -1252,7 +1252,7 @@ static int cmsis_dap_init(void)
 
        /* Now try to connect to the target
         * TODO: This is all SWD only @ present */
-       retval = cmsis_dap_cmd_dap_swj_clock(jtag_get_speed_khz());
+       retval = cmsis_dap_cmd_dap_swj_clock(adapter_get_speed_khz());
        if (retval != ERROR_OK)
                goto init_err;
 
@@ -1394,18 +1394,18 @@ static void debug_parse_cmsis_buf(const uint8_t *cmd, int cmdlen)
        for (int i = 0; i < cmdlen; ++i)
                printf(" %02x", cmd[i]);
        printf("\n");
-       switch (cmd[1]) {
+       switch (cmd[0]) {
                case CMD_DAP_JTAG_SEQ: {
-                       printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[1], cmd[2]);
+                       printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[0], cmd[1]);
                        /*
-                        * #2 = number of sequences
-                        * #3 = sequence info 1
-                        * #4...4+n_bytes-1 = sequence 1
+                        * #1 = number of sequences
+                        * #2 = sequence info 1
+                        * #3...4+n_bytes-1 = sequence 1
                         * #4+n_bytes = sequence info 2
                         * #5+n_bytes = sequence 2 (single bit)
                         */
-                       int pos = 3;
-                       for (int seq = 0; seq < cmd[2]; ++seq) {
+                       int pos = 2;
+                       for (int seq = 0; seq < cmd[1]; ++seq) {
                                uint8_t info = cmd[pos++];
                                int len = info & DAP_JTAG_SEQ_TCK;
                                if (len == 0)
@@ -1513,7 +1513,7 @@ static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int
                                s_offset + offset,
                                tms,
                                tdo_buffer,
-                               tdo_buffer == NULL ? 0 : (tdo_buffer_offset + offset)
+                               !tdo_buffer ? 0 : (tdo_buffer_offset + offset)
                                );
                }
                LOG_DEBUG_IO("END JTAG SEQ SPLIT");
@@ -1530,17 +1530,17 @@ static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int
        /* control byte */
        queued_seq_buf[queued_seq_buf_end] =
                (tms ? DAP_JTAG_SEQ_TMS : 0) |
-               (tdo_buffer != NULL ? DAP_JTAG_SEQ_TDO : 0) |
+               (tdo_buffer ? DAP_JTAG_SEQ_TDO : 0) |
                (s_len == 64 ? 0 : s_len);
 
-       if (sequence != NULL)
+       if (sequence)
                bit_copy(&queued_seq_buf[queued_seq_buf_end + 1], 0, sequence, s_offset, s_len);
        else
                memset(&queued_seq_buf[queued_seq_buf_end + 1], 0, DIV_ROUND_UP(s_len, 8));
 
        queued_seq_buf_end += cmd_len;
 
-       if (tdo_buffer != NULL) {
+       if (tdo_buffer) {
                struct pending_scan_result *scan = &pending_scan_results[pending_scan_result_count++];
                scan->first = queued_seq_tdo_ptr;
                queued_seq_tdo_ptr += DIV_ROUND_UP(s_len, 8);
@@ -1799,7 +1799,7 @@ static int cmsis_dap_execute_queue(void)
 {
        struct jtag_command *cmd = jtag_command_queue;
 
-       while (cmd != NULL) {
+       while (cmd) {
                cmsis_dap_execute_command(cmd);
                cmd = cmd->next;
        }
@@ -1995,7 +1995,7 @@ COMMAND_HANDLER(cmsis_dap_handle_cmd_command)
        uint8_t *command = cmsis_dap_handle->command;
 
        for (unsigned i = 0; i < CMD_ARGC; i++)
-               command[i] = strtoul(CMD_ARGV[i], NULL, 16);
+               COMMAND_PARSE_NUMBER(u8, CMD_ARGV[i], command[i]);
 
        int retval = cmsis_dap_xfer(cmsis_dap_handle, CMD_ARGC);
 
@@ -2041,16 +2041,6 @@ COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command)
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(cmsis_dap_handle_serial_command)
-{
-       if (CMD_ARGC == 1)
-               cmsis_dap_serial = strdup(CMD_ARGV[0]);
-       else
-               LOG_ERROR("expected exactly one argument to cmsis_dap_serial <serial-number>");
-
-       return ERROR_OK;
-}
-
 COMMAND_HANDLER(cmsis_dap_handle_backend_command)
 {
        if (CMD_ARGC == 1) {
@@ -2107,13 +2097,6 @@ static const struct command_registration cmsis_dap_command_handlers[] = {
                .help = "the vendor ID and product ID of the CMSIS-DAP device",
                .usage = "(vid pid)*",
        },
-       {
-               .name = "cmsis_dap_serial",
-               .handler = &cmsis_dap_handle_serial_command,
-               .mode = COMMAND_CONFIG,
-               .help = "set the serial number of the adapter",
-               .usage = "serial_string",
-       },
        {
                .name = "cmsis_dap_backend",
                .handler = &cmsis_dap_handle_backend_command,

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)