From d6ade4d94ea63fbe9596ec96fadbac003ef48730 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 12 Feb 2021 19:14:03 +0100 Subject: [PATCH] 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 a4056eb..d2b6c75 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 5451f8c..8f5189c 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 6f9a23c..c9ce20b 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 037e0f0..470742c 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 fc4d101..5b75832 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: