From fa561c8d66bfee828b7998a14393ec1a112c7231 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 10 Feb 2021 16:53:20 +0100 Subject: [PATCH 1/4] adiv5_swdp: Starting point to handle multi-drop - RP2040 show both DPs - Multidrop test with STM32L552 and STM32H745 allows selection with "-m 0x4500041" (H7), "-m 1" (L552) or "-m 0x01002927" (RP2040) --- src/target/adiv5.c | 7 -- src/target/adiv5.h | 14 ++-- src/target/adiv5_swdp.c | 156 +++++++++++++++++++++++++++++++--------- 3 files changed, 132 insertions(+), 45 deletions(-) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 50a42664..fe3f4579 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -707,13 +707,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp) } } - if ((dp->idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { - /* Read TargetID. Can be done with device in WFI, sleep or reset!*/ - adiv5_dp_write(dp, ADIV5_DP_SELECT, ADIV5_DP_BANK2); - dp->targetid = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); - adiv5_dp_write(dp, ADIV5_DP_SELECT, ADIV5_DP_BANK0); - DEBUG_INFO("TARGETID %08" PRIx32 "\n", dp->targetid); - } /* Probe for APs on this DP */ uint32_t last_base = 0; int void_aps = 0; diff --git a/src/target/adiv5.h b/src/target/adiv5.h index 38c1cccb..c143910d 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -27,18 +27,20 @@ #define ADIV5_DP_REG(x) (x) #define ADIV5_AP_REG(x) (ADIV5_APnDP | (x)) +#define ADIV5_DP_BANK0 0x00 +#define ADIV5_DP_BANK1 0x10 +#define ADIV5_DP_BANK2 0x20 +#define ADIV5_DP_BANK3 0x30 +#define ADIV5_DP_BANK4 0x40 + /* ADIv5 DP Register addresses */ #define ADIV5_DP_IDCODE ADIV5_DP_REG(0x0) #define ADIV5_DP_ABORT ADIV5_DP_REG(0x0) #define ADIV5_DP_CTRLSTAT ADIV5_DP_REG(0x4) +#define ADIV5_DP_TARGETID (ADIV5_DP_BANK2 | ADIV5_DP_REG(0x4)) #define ADIV5_DP_SELECT ADIV5_DP_REG(0x8) #define ADIV5_DP_RDBUFF ADIV5_DP_REG(0xC) - -#define ADIV5_DP_BANK0 0 -#define ADIV5_DP_BANK1 1 -#define ADIV5_DP_BANK2 2 -#define ADIV5_DP_BANK3 3 -#define ADIV5_DP_BANK4 4 +#define ADIV5_DP_TARGETSEL ADIV5_DP_REG(0xC) #define ADIV5_DP_VERSION_MASK 0xf000 #define ADIV5_DPv1 0x1000 diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 24af6c49..5a5336d2 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -49,10 +49,51 @@ static unsigned int make_packet_request(uint8_t RnW, uint16_t addr) return request; } +/* Provide bare DP access functions without timeout and exception */ + +static void dp_line_reset(void) +{ + swd_proc.swdptap_seq_out(0xFFFFFFFF, 32); + swd_proc.swdptap_seq_out(0x0FFFFFFF, 32); +} + +static void dp_write(uint16_t addr, const uint32_t data) +{ + int bank = (addr >> 4) & 0xf; + unsigned int request; + if (bank) + dp_write(ADIV5_DP_SELECT, bank); + request = make_packet_request(ADIV5_LOW_WRITE, addr & 0xf); + swd_proc.swdptap_seq_out(request, 8); + swd_proc.swdptap_seq_in(3); + swd_proc.swdptap_seq_out_parity(data, 32); + if (bank) + dp_write(ADIV5_DP_SELECT, 0); +} + +static bool dp_read(uint16_t addr, uint32_t *res) +{ + int bank = (addr >> 4) & 0xf; + unsigned int request; + if (bank) + dp_write(ADIV5_DP_SELECT, bank); + request = make_packet_request(ADIV5_LOW_READ, addr & 0xf); + swd_proc.swdptap_seq_out(request, 8); + swd_proc.swdptap_seq_in(3); + if (swd_proc.swdptap_seq_in_parity(res, 32)) { + return true; + } + if (bank) + dp_write(ADIV5_DP_SELECT, 0); + return false; +} + +/* Try first the dormant to SWD procedure. + * If target id given, scan DPs 0 .. 15 on that device and return. + * Otherwise + */ int adiv5_swdp_scan(uint32_t targetid) { - uint32_t ack; - (void) targetid; target_list_free(); #if PC_HOSTED == 1 if (platform_swdptap_init()) { @@ -64,41 +105,83 @@ int adiv5_swdp_scan(uint32_t targetid) } #endif - /* Switch from JTAG to SWD mode */ - swd_proc.swdptap_seq_out(0xFFFFFFFF, 16); + /* DORMANT-> SWD sequence*/ swd_proc.swdptap_seq_out(0xFFFFFFFF, 32); - swd_proc.swdptap_seq_out(0xFFFFFFFF, 18); - swd_proc.swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ swd_proc.swdptap_seq_out(0xFFFFFFFF, 32); - swd_proc.swdptap_seq_out(0xFFFFFFFF, 18); - swd_proc.swdptap_seq_out(0, 16); - - /* Read the SW-DP IDCODE register to syncronise */ - /* This could be done with adiv_swdp_low_access(), but this doesn't - * allow the ack to be checked here. */ - uint32_t request = make_packet_request(ADIV5_LOW_READ, ADIV5_DP_IDCODE); - swd_proc.swdptap_seq_out(request, 8); - ack = swd_proc.swdptap_seq_in(3); - uint32_t idcode; - if((ack != SWDP_ACK_OK) || swd_proc.swdptap_seq_in_parity(&idcode, 32)) { - DEBUG_WARN("Read SW-DP IDCODE failed %1" PRIx32 "\n", ack); - return -1; + /* 128 bit selection alert sequence for SW-DP-V2 */ + swd_proc.swdptap_seq_out(0x6209f392, 32); + swd_proc.swdptap_seq_out(0x86852d95, 32); + swd_proc.swdptap_seq_out(0xe3ddafe9, 32); + swd_proc.swdptap_seq_out(0x19bc0ea2, 32); + /* 4 cycle low, + * 0x1a Arm CoreSight SW-DP activation sequence + * 20 bits start of reset another reset sequence*/ + swd_proc.swdptap_seq_out(0x1a0, 12); + uint32_t idcode = 0; + uint32_t target_id; + bool is_v2 = true; + if (!targetid) { + /* Try to read ID */ + dp_line_reset(); + bool res = dp_read(ADIV5_DP_IDCODE, &idcode); + if (res) { + is_v2 = false; + DEBUG_WARN("Trying old JTAG to SWD sequence\n"); + swd_proc.swdptap_seq_out(0xFFFFFFFF, 32); + swd_proc.swdptap_seq_out(0xFFFFFFFF, 32); + swd_proc.swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ + dp_line_reset(); + bool res = dp_read(ADIV5_DP_IDCODE, &idcode); + if (res) { + DEBUG_WARN("No usable DP found\n"); + return -1; + } + } + if ((idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { + is_v2 = true; + bool res = dp_read(ADIV5_DP_TARGETID, &target_id); + if (res) { + DEBUG_WARN("Read Targetid failed\n"); + return -1; + } + } else { + is_v2 = false; + } + } else { + target_id = targetid; } + int nr_dps = (is_v2) ? 16: 1; + uint32_t dp_targetid; + for (int i = 0; i < nr_dps; i++) { + if (is_v2) { + dp_line_reset(); + dp_targetid = (i << 28) | (target_id & 0x0fffffff); + dp_write(ADIV5_DP_TARGETSEL, dp_targetid); + bool res = dp_read(ADIV5_DP_IDCODE, &idcode); + if (res) + continue; + if (dp_targetid == 0xf1002927) /* Fixme: Handle RP2040 rescue port */ + continue; + DEBUG_WARN("DP %2d IDCODE %08" PRIx32 " TID 0x%08" PRIx32 "\n", i, idcode, dp_targetid); + } else { + dp_targetid = 0; + } + ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); + if (!dp) { /* calloc failed: heap exhaustion */ + DEBUG_WARN("calloc: failed in %s\n", __func__); + continue; + } + dp->idcode = idcode; + dp->targetid = dp_targetid; + dp->dp_read = firmware_swdp_read; + dp->error = firmware_swdp_error; + dp->low_access = firmware_swdp_low_access; + dp->abort = firmware_swdp_abort; + + firmware_swdp_error(dp); + adiv5_dp_init(dp); - ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); - if (!dp) { /* calloc failed: heap exhaustion */ - DEBUG_WARN("calloc: failed in %s\n", __func__); - return -1; } - - dp->idcode = idcode; - dp->dp_read = firmware_swdp_read; - dp->error = firmware_swdp_error; - dp->low_access = firmware_swdp_low_access; - dp->abort = firmware_swdp_abort; - - firmware_swdp_error(dp); - adiv5_dp_init(dp); return target_list?1:0; } @@ -117,6 +200,15 @@ uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr) { uint32_t err, clr = 0; + if ((dp->idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { + /* On protocoll error target gets deselected. + * With DP Change, another target needs selection. + * => Reselect with right target! */ + dp_line_reset(); + dp_write(ADIV5_DP_TARGETSEL, dp->targetid); + uint32_t dummy; + dp_read(ADIV5_DP_IDCODE, &dummy); + } err = firmware_swdp_read(dp, ADIV5_DP_CTRLSTAT) & (ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP | ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR); From 5abb288c7a61bb9558d984ad852286a4ae43eec1 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 12 Feb 2021 11:41:26 +0100 Subject: [PATCH 2/4] hosted: Provide the DP functions in swd_proc. --- src/include/swdptap.h | 9 +++++++++ src/platforms/hosted/libftdi_swdptap.c | 8 +++++--- src/platforms/hosted/remote_swdptap.c | 7 +++++-- src/target/adiv5_swdp.c | 9 ++++++++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/include/swdptap.h b/src/include/swdptap.h index 87cfe160..1254dd0d 100644 --- a/src/include/swdptap.h +++ b/src/include/swdptap.h @@ -20,11 +20,20 @@ #ifndef __SWDPTAP_H #define __SWDPTAP_H +#include "adiv5.h" + typedef struct swd_proc_s { uint32_t (*swdptap_seq_in)(int ticks); bool (*swdptap_seq_in_parity)(uint32_t *data, int ticks); void (*swdptap_seq_out)(uint32_t MS, int ticks); void (*swdptap_seq_out_parity)(uint32_t MS, int ticks); +# if PC_HOSTED == 1 + uint32_t (*swdp_read)(ADIv5_DP_t *dp, uint16_t addr); + uint32_t (*swdp_error)(ADIv5_DP_t *dp); + uint32_t (*swdp_low_access)(ADIv5_DP_t *dp, uint8_t RnW, + uint16_t addr, uint32_t value); + void (*swdp_abort)(ADIv5_DP_t *dp, uint32_t abort); +#endif } swd_proc_t; extern swd_proc_t swd_proc; diff --git a/src/platforms/hosted/libftdi_swdptap.c b/src/platforms/hosted/libftdi_swdptap.c index b76cb06f..3d5c24c8 100644 --- a/src/platforms/hosted/libftdi_swdptap.c +++ b/src/platforms/hosted/libftdi_swdptap.c @@ -1,8 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2018 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) - * Written by Gareth McMullin + * Copyright(C) 2018 - 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * * 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 @@ -212,7 +211,10 @@ int libftdi_swdptap_init(swd_proc_t *swd_proc) swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity; swd_proc->swdptap_seq_out = swdptap_seq_out; swd_proc->swdptap_seq_out_parity = swdptap_seq_out_parity; - + swd_proc->swdp_read = firmware_swdp_read; + swd_proc->swdp_error = firmware_swdp_error; + swd_proc->swdp_low_access = firmware_swdp_low_access; + swd_proc->swdp_abort = firmware_swdp_abort; return 0; } diff --git a/src/platforms/hosted/remote_swdptap.c b/src/platforms/hosted/remote_swdptap.c index 134de846..ee9b7362 100644 --- a/src/platforms/hosted/remote_swdptap.c +++ b/src/platforms/hosted/remote_swdptap.c @@ -3,7 +3,7 @@ * * Written by Gareth McMullin * Modified by Dave Marples - * Modification (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) + * Modified 2020 - 2021 by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * * 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 @@ -54,7 +54,10 @@ int remote_swdptap_init(swd_proc_t *swd_proc) swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity; swd_proc->swdptap_seq_out = swdptap_seq_out; swd_proc->swdptap_seq_out_parity = swdptap_seq_out_parity; - + swd_proc->swdp_read = firmware_swdp_read; + swd_proc->swdp_error = firmware_swdp_error; + swd_proc->swdp_low_access = firmware_swdp_low_access; + swd_proc->swdp_abort = firmware_swdp_abort; return 0; } diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 5a5336d2..2a686de2 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -173,12 +173,19 @@ int adiv5_swdp_scan(uint32_t targetid) } dp->idcode = idcode; dp->targetid = dp_targetid; +#if HOSTED == 0 dp->dp_read = firmware_swdp_read; dp->error = firmware_swdp_error; dp->low_access = firmware_swdp_low_access; dp->abort = firmware_swdp_abort; - firmware_swdp_error(dp); +#else + dp->dp_read = swd_proc->swdp_read; + dp->error = swd_proc->swdp_error; + dp->low_access = swd_proc->swdp_low_access; + dp->abort = swd_proc->swdp_abort; + swd_proc->swdp_error(); +#endif adiv5_dp_init(dp); } From d6ade4d94ea63fbe9596ec96fadbac003ef48730 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 12 Feb 2021 19:14:03 +0100 Subject: [PATCH 3/4] cmsis-dap: Use SWD_SEQUENCE if available. --- src/platforms/hosted/cmsis_dap.c | 73 ++++++++++++++++++------------- src/platforms/hosted/cmsis_dap.h | 8 +++- src/platforms/hosted/dap.c | 74 +++++++++++++++++++++++++++++++- src/platforms/hosted/dap.h | 4 ++ src/platforms/hosted/platform.c | 29 ++++++++----- 5 files changed, 144 insertions(+), 44 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index a4056eb0..d2b6c757 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -35,6 +35,7 @@ #include #include "bmp_hosted.h" +#include "swdptap.h" #include "dap.h" #include "cmsis_dap.h" @@ -79,12 +80,12 @@ int dap_init(bmp_info_t *info) if (sscanf((const char *)hid_buffer, "%d.%d.%d", &major, &minor, &sub)) { if (sub == -1) { - if (minor > 10) { + if (minor >= 10) { minor /= 10; sub = 0; } } - has_swd_sequence = ((major > 0 ) && (minor > 1)); + has_swd_sequence = ((major > 1 ) || ((major > 0 ) && (minor > 1))); } } size = dap_info(DAP_INFO_CAPABILITIES, hid_buffer, sizeof(hid_buffer)); @@ -176,7 +177,7 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) memcpy(&hid_buffer[1], data, rsize); DEBUG_WIRE("cmd : "); - for(int i = 0; (i < 16) && (i < rsize + 1); i++) + for(int i = 1; (i < 16) && (i < rsize + 1); i++) DEBUG_WIRE("%02x.", hid_buffer[i]); DEBUG_WIRE("\n"); res = hid_write(handle, hid_buffer, rsize + 1); @@ -184,24 +185,21 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) DEBUG_WARN( "Error: %ls\n", hid_error(handle)); exit(-1); } - if (size) { - res = hid_read(handle, hid_buffer, report_size + 1); - if (res < 0) { - DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle)); - exit(-1); - } - if (size && hid_buffer[0] != cmd) { - DEBUG_WARN("cmd %02x invalid response received %02x\n", - cmd, hid_buffer[0]); - } - res--; - memcpy(data, &hid_buffer[1], (size < res) ? size : res); - DEBUG_WIRE("cmd res:"); - for(int i = 0; (i < 16) && (i < size + 4); i++) - DEBUG_WIRE("%02x.", hid_buffer[i]); - DEBUG_WIRE("\n"); + res = hid_read(handle, hid_buffer, report_size + 1); + if (res < 0) { + DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle)); + exit(-1); } - + if (hid_buffer[0] != cmd) { + DEBUG_WARN("cmd %02x invalid response received %02x\n", + cmd, hid_buffer[0]); + } + DEBUG_WIRE("cmd res:"); + for(int i = 0; (i < 16) && (i < size + 1); i++) + DEBUG_WIRE("%02x.", hid_buffer[i]); + DEBUG_WIRE("\n"); + if (size) + memcpy(data, &hid_buffer[1], (size < res) ? size : res); return res; } #define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \ @@ -283,16 +281,6 @@ static void dap_mem_write_sized( int dap_enter_debug_swd(ADIv5_DP_t *dp) { - target_list_free(); - if (!(dap_caps & DAP_CAP_SWD)) - return -1; - mode = DAP_CAP_SWD; - dap_transfer_configure(2, 128, 128); - dap_swd_configure(0); - dap_connect(false); - dap_led(0, 1); - dap_reset_link(false); - dp->idcode = dap_read_idcode(dp); dp->dp_read = dap_dp_read_reg; dp->error = dap_dp_error; @@ -355,12 +343,12 @@ int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc) mode = DAP_CAP_JTAG; dap_disconnect(); dap_connect(true); + dap_reset_link(true); jtag_proc->jtagtap_reset = cmsis_dap_jtagtap_reset; jtag_proc->jtagtap_next = cmsis_dap_jtagtap_next; jtag_proc->jtagtap_tms_seq = cmsis_dap_jtagtap_tms_seq; jtag_proc->jtagtap_tdi_tdo_seq = cmsis_dap_jtagtap_tdi_tdo_seq; jtag_proc->jtagtap_tdi_seq = cmsis_dap_jtagtap_tdi_seq; - dap_reset_link(true); return 0; } @@ -373,3 +361,26 @@ int dap_jtag_dp_init(ADIv5_DP_t *dp) return true; } + +int dap_swdptap_init(swd_proc_t *swd_proc) +{ + if (!(dap_caps & DAP_CAP_SWD)) + return 1; + mode = DAP_CAP_SWD; + dap_transfer_configure(2, 128, 128); + dap_swd_configure(0); + dap_connect(false); + dap_led(0, 1); + dap_reset_link(false); + if (has_swd_sequence) { + swd_proc->swdptap_seq_in = dap_swdptap_seq_in; + swd_proc->swdptap_seq_in_parity = dap_swdptap_seq_in_parity; + swd_proc->swdptap_seq_out = dap_swdptap_seq_out; + swd_proc->swdptap_seq_out_parity = dap_swdptap_seq_out_parity; + swd_proc->swdp_read = dap_dp_read_reg; + swd_proc->swdp_error = dap_dp_error; + swd_proc->swdp_low_access = dap_dp_low_access; + swd_proc->swdp_abort = dap_dp_abort; + } + return 0; +} diff --git a/src/platforms/hosted/cmsis_dap.h b/src/platforms/hosted/cmsis_dap.h index 5451f8cf..8f5189c5 100644 --- a/src/platforms/hosted/cmsis_dap.h +++ b/src/platforms/hosted/cmsis_dap.h @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2019 Uwe Bonnes + * Copyright (C) 2019 - 2021 Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de) * * 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 @@ -28,8 +28,10 @@ int dap_enter_debug_swd(ADIv5_DP_t *dp); void dap_exit_function(void); void dap_adiv5_dp_defaults(ADIv5_DP_t *dp); int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc); +int dap_swdptap_init(swd_proc_t *swd_proc); int dap_jtag_dp_init(ADIv5_DP_t *dp); uint32_t dap_swj_clock(uint32_t clock); +void dap_swd_configure(uint8_t cfg); #else int dap_init(bmp_info_t *info) { @@ -44,8 +46,10 @@ uint32_t dap_swj_clock(uint32_t clock) {return 0;} void dap_exit_function(void) {}; void dap_adiv5_dp_defaults(ADIv5_DP_t *dp) {}; int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc) {return -1;} +int dap_swdptap_init(swd_proc_t *swd_proc) {return -1;} int dap_jtag_dp_init(ADIv5_DP_t *dp) {return -1;} -# pragma GCC diagnostic pop +void dap_swd_configure(uint8_t cfg) {}; +## pragma GCC diagnostic pop #endif diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 6f9a23c1..c9ce20be 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -27,7 +27,7 @@ */ /* Modified for Blackmagic Probe - * Copyright (c) 2020 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de + * Copyright (c) 2020-21 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de */ /*- Includes ----------------------------------------------------------------*/ @@ -57,6 +57,7 @@ enum ID_DAP_JTAG_SEQUENCE = 0x14, ID_DAP_JTAG_CONFIGURE = 0x15, ID_DAP_JTAG_IDCODE = 0x16, + ID_DAP_SWD_SEQUENCE = 0x1D, }; enum @@ -750,3 +751,74 @@ int dap_jtag_configure(void) DEBUG_WARN("dap_jtag_configure Failed %02x\n", buf[0]); return 0; } + +void dap_swdptap_seq_out(uint32_t MS, int ticks) +{ + uint8_t buf[] = { + ID_DAP_SWJ_SEQUENCE, + ticks, + (MS >> 0) & 0xff, + (MS >> 8) & 0xff, + (MS >> 16) & 0xff, + (MS >> 24) & 0xff + }; + dbg_dap_cmd(buf, 1, sizeof(buf)); + if (buf[0]) + DEBUG_WARN("dap_swdptap_seq_out error\n"); +} + +void dap_swdptap_seq_out_parity(uint32_t MS, int ticks) +{ + uint8_t buf[] = { + ID_DAP_SWJ_SEQUENCE, + ticks + 1, + (MS >> 0) & 0xff, + (MS >> 8) & 0xff, + (MS >> 16) & 0xff, + (MS >> 24) & 0xff, + __builtin_parity(MS) & 1 + }; + dbg_dap_cmd(buf, 1, sizeof(buf)); + if (buf[0]) + DEBUG_WARN("dap_swdptap_seq_out error\n"); +} + +#define SWD_SEQUENCE_IN 0x80 +uint32_t dap_swdptap_seq_in(int ticks) +{ + uint8_t buf[5] = { + ID_DAP_SWD_SEQUENCE, + 1, + ticks + SWD_SEQUENCE_IN + }; + dbg_dap_cmd(buf, 2 + ((ticks + 7) >> 3), 3); + uint32_t res = 0; + int len = (ticks + 7) >> 3; + while (len--) { + res <<= 8; + res += buf[len + 1]; + } + return res; +} + +bool dap_swdptap_seq_in_parity(uint32_t *ret, int ticks) +{ + (void)ticks; + uint8_t buf[8] = { + ID_DAP_SWD_SEQUENCE, + 1, + 33 + SWD_SEQUENCE_IN, + }; + dbg_dap_cmd(buf, 7, 4); + uint32_t res = 0; + int len = 4; + while (len--) { + res <<= 8; + res += buf[len + 1]; + } + *ret = res; + unsigned int parity = __builtin_parity(res) & 1; + parity ^= (buf[5] % 1); + DEBUG_WARN("Res %08" PRIx32" %d\n", *ret, parity & 1); + return (!parity & 1); +} diff --git a/src/platforms/hosted/dap.h b/src/platforms/hosted/dap.h index 037e0f08..470742ca 100644 --- a/src/platforms/hosted/dap.h +++ b/src/platforms/hosted/dap.h @@ -90,4 +90,8 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize); void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, const uint8_t *DI, int ticks); int dap_jtag_configure(void); +void dap_swdptap_seq_out(uint32_t MS, int ticks); +void dap_swdptap_seq_out_parity(uint32_t MS, int ticks); +uint32_t dap_swdptap_seq_in(int ticks); +bool dap_swdptap_seq_in_parity(uint32_t *ret, int ticks); #endif // _DAP_H_ diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index fc4d1011..5b758329 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -144,18 +144,26 @@ int platform_adiv5_swdp_scan(uint32_t targetid) break; } case BMP_TYPE_CMSIS_DAP: - { - target_list_free(); - ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); - if (dap_enter_debug_swd(dp)) { - free(dp); + if (dap_swdptap_init(&swd_proc)) + return 0; + if (swd_proc.swdptap_seq_in) { + dap_swd_configure(4); /* No abort for now*/ + return adiv5_swdp_scan(targetid); } else { - adiv5_dp_init(dp); - if (target_list) - return 1; + /* We need to ignore errors with TARGET_SEL. + * Therefore we need DAP_SWD_Sequence obly available on >= V1.2 + */ + target_list_free(); + ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); + if (dap_enter_debug_swd(dp)) { + free(dp); + } else { + adiv5_dp_init(dp); + if (target_list) + return 1; + } } break; - } case BMP_TYPE_JLINK: return jlink_swdp_scan(&info); default: @@ -169,8 +177,9 @@ int platform_swdptap_init(void) switch (info.bmp_type) { case BMP_TYPE_BMP: return remote_swdptap_init(&swd_proc); - case BMP_TYPE_STLINKV2: case BMP_TYPE_CMSIS_DAP: +// return dap_swdptap_init(&swd_proc); + case BMP_TYPE_STLINKV2: case BMP_TYPE_JLINK: return 0; case BMP_TYPE_LIBFTDI: From 61e237ec87c525876817e72fc82ce28b2a4951ae Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 13 Feb 2021 17:42:00 +0100 Subject: [PATCH 4/4] cmsis_dap: Always write full reportsize + 1 buffers Expect short reads and other errors else --- src/platforms/hosted/cmsis_dap.c | 24 +++++++++++++++--------- src/platforms/hosted/dap.c | 15 ++++++++------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index d2b6c757..786441fa 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -67,7 +67,7 @@ int dap_init(bmp_info_t *info) */ if ((info->vid == 0x1fc9) && (info->pid == 0x0132)) { DEBUG_WARN("Blacklist\n"); - report_size = 64 + 1; + report_size = 64; } handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL); if (!handle) @@ -100,6 +100,11 @@ int dap_init(bmp_info_t *info) DEBUG_INFO(", SWO_MANCHESTER"); if (dap_caps & 0x10) DEBUG_INFO(", Atomic Cmds"); + size = dap_info(DAP_INFO_PACKET_SIZE, hid_buffer, sizeof(hid_buffer)); + if (size) { + report_size = hid_buffer[0]; + DEBUG_INFO(", Reportsize %d", hid_buffer[0]); + } DEBUG_INFO("\n"); return 0; } @@ -171,16 +176,17 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) char cmd = data[0]; int res; - memset(hid_buffer, 0xff, report_size + 1); + memset(hid_buffer, 0, report_size + 1); - hid_buffer[0] = 0x00; // Report ID?? memcpy(&hid_buffer[1], data, rsize); DEBUG_WIRE("cmd : "); - for(int i = 1; (i < 16) && (i < rsize + 1); i++) + for(int i = 0; (i < 16) && (i < rsize + 1); i++) DEBUG_WIRE("%02x.", hid_buffer[i]); DEBUG_WIRE("\n"); - res = hid_write(handle, hid_buffer, rsize + 1); + /* Write must be as long as we expect the result, at least + * for Dappermime 20210213 */ + res = hid_write(handle, hid_buffer, report_size + 1); if (res < 0) { DEBUG_WARN( "Error: %ls\n", hid_error(handle)); exit(-1); @@ -190,14 +196,14 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle)); exit(-1); } + DEBUG_WIRE("res %2d: ", res); + for(int i = 0; (i < 16) && (i < res + 1); i++) + DEBUG_WIRE("%02x.", hid_buffer[i]); + DEBUG_WIRE("\n"); if (hid_buffer[0] != cmd) { DEBUG_WARN("cmd %02x invalid response received %02x\n", cmd, hid_buffer[0]); } - DEBUG_WIRE("cmd res:"); - for(int i = 0; (i < 16) && (i < size + 1); i++) - DEBUG_WIRE("%02x.", hid_buffer[i]); - DEBUG_WIRE("\n"); if (size) memcpy(data, &hid_buffer[1], (size < res) ? size : res); return res; diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index c9ce20be..0cf63e32 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -198,7 +198,7 @@ void dap_connect(bool jtag) //----------------------------------------------------------------------------- void dap_disconnect(void) { - uint8_t buf[1]; + uint8_t buf[65]; buf[0] = ID_DAP_DISCONNECT; dbg_dap_cmd(buf, sizeof(buf), 1); @@ -213,7 +213,7 @@ uint32_t dap_swj_clock(uint32_t clock) { if (clock == 0) return swj_clock; - uint8_t buf[5]; + uint8_t buf[65]; buf[0] = ID_DAP_SWJ_CLOCK; buf[1] = clock & 0xff; buf[2] = (clock >> 8) & 0xff; @@ -254,7 +254,7 @@ void dap_swd_configure(uint8_t cfg) //----------------------------------------------------------------------------- int dap_info(int info, uint8_t *data, int size) { - uint8_t buf[256]; + uint8_t buf[32]; int rsize; buf[0] = ID_DAP_INFO; @@ -786,7 +786,7 @@ void dap_swdptap_seq_out_parity(uint32_t MS, int ticks) #define SWD_SEQUENCE_IN 0x80 uint32_t dap_swdptap_seq_in(int ticks) { - uint8_t buf[5] = { + uint8_t buf[16] = { ID_DAP_SWD_SEQUENCE, 1, ticks + SWD_SEQUENCE_IN @@ -804,10 +804,11 @@ uint32_t dap_swdptap_seq_in(int ticks) bool dap_swdptap_seq_in_parity(uint32_t *ret, int ticks) { (void)ticks; - uint8_t buf[8] = { + uint8_t buf[16] = { ID_DAP_SWD_SEQUENCE, - 1, - 33 + SWD_SEQUENCE_IN, + 2, + 32 + SWD_SEQUENCE_IN, + 1 + SWD_SEQUENCE_IN, }; dbg_dap_cmd(buf, 7, 4); uint32_t res = 0;