openocd: fix SPDX tag format for files .c
[fw/openocd] / 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,