From 80ddafc2f883f7e8a6452507e4c7afbfbd93883c Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 19 Oct 2020 13:13:43 +0200 Subject: [PATCH 01/20] Jtag/High Level : Transfer dp->dp_jd_index with every HL command. - Add REMOTE_HL_VERSION, now at 1. Fall back to hosted/low-level when wrong version is found and give hint to user. --- src/platforms/hosted/bmp_remote.c | 26 ++++++++------------------ src/remote.c | 17 ++++++----------- src/remote.h | 22 ++++++++++------------ 3 files changed, 24 insertions(+), 41 deletions(-) diff --git a/src/platforms/hosted/bmp_remote.c b/src/platforms/hosted/bmp_remote.c index e42ac54b..12387151 100644 --- a/src/platforms/hosted/bmp_remote.c +++ b/src/platforms/hosted/bmp_remote.c @@ -153,7 +153,7 @@ static uint32_t remote_adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr) (void)dp; uint8_t construct[REMOTE_MAX_MSG_SIZE]; int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_DP_READ_STR, - addr); + dp->dp_jd_index, addr); platform_buffer_write(construct, s); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { @@ -171,7 +171,7 @@ static uint32_t remote_adiv5_low_access( (void)dp; uint8_t construct[REMOTE_MAX_MSG_SIZE]; int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, - REMOTE_LOW_ACCESS_STR, RnW, addr, value); + REMOTE_LOW_ACCESS_STR, dp->dp_jd_index, RnW, addr, value); platform_buffer_write(construct, s); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { @@ -186,7 +186,7 @@ static uint32_t remote_adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr) { uint8_t construct[REMOTE_MAX_MSG_SIZE]; int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_AP_READ_STR, - ap->apsel, addr); + ap->dp->dp_jd_index, ap->apsel, addr); platform_buffer_write(construct, s); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { @@ -201,7 +201,7 @@ static void remote_adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value) { uint8_t construct[REMOTE_MAX_MSG_SIZE]; int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_AP_WRITE_STR, - ap->apsel, addr, value); + ap->dp->dp_jd_index, ap->apsel, addr, value); platform_buffer_write(construct, s); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { @@ -267,7 +267,7 @@ static void remote_ap_mem_read( if (count > batchsize) count = batchsize; s = snprintf(construct, REMOTE_MAX_MSG_SIZE, - REMOTE_AP_MEM_READ_STR, ap->apsel, ap->csw, src, count); + REMOTE_AP_MEM_READ_STR, ap->dp->dp_jd_index, ap->apsel, ap->csw, src, count); platform_buffer_write((uint8_t*)construct, s); s = platform_buffer_read((uint8_t*)construct, REMOTE_MAX_MSG_SIZE); if ((s > 0) && (construct[0] == REMOTE_RESP_OK)) { @@ -307,7 +307,7 @@ static void remote_ap_mem_write_sized( count = batchsize; int s = snprintf(construct, REMOTE_MAX_MSG_SIZE, REMOTE_AP_MEM_WRITE_SIZED_STR, - ap->apsel, ap->csw, align, dest, count); + ap->dp->dp_jd_index, ap->apsel, ap->csw, align, dest, count); char *p = construct + s; hexify(p, src, count); p += 2 * count; @@ -340,22 +340,12 @@ void remote_adiv5_dp_defaults(ADIv5_DP_t *dp) REMOTE_HL_CHECK_STR); platform_buffer_write(construct, s); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + if ((!s) || (construct[0] == REMOTE_RESP_ERR) || + ((construct[1] - '0') < REMOTE_HL_VERSION)) { DEBUG_WARN( "Please update BMP firmware for substantial speed increase!\n"); return; } - if (dp->dp_jd_index < JTAG_MAX_DEVS) { - s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_HL_JTAG_DEV_STR, - dp->dp_jd_index); - platform_buffer_write(construct, s); - s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] != REMOTE_RESP_OK)) { - DEBUG_WARN( - "Please update BMP firmware to allow high level jtag commands!\n"); - return; - } - } dp->low_access = remote_adiv5_low_access; dp->dp_read = remote_adiv5_dp_read; dp->ap_write = remote_adiv5_ap_write; diff --git a/src/remote.c b/src/remote.c index 3e0a70e1..445d18ec 100644 --- a/src/remote.c +++ b/src/remote.c @@ -322,21 +322,16 @@ void remotePacketProcessHL(uint8_t i, char *packet) /* Re-use packet buffer. Align to DWORD! */ void *src = (void *)(((uint32_t)packet + 7) & ~7); char index = packet[1]; + if (index == REMOTE_HL_CHECK) { + _respond(REMOTE_RESP_OK, REMOTE_HL_VERSION); + return; + } + packet += 2; + remote_dp.dp_jd_index = remotehston(2, packet); packet += 2; remote_ap.apsel = remotehston(2, packet); remote_ap.dp = &remote_dp; switch (index) { - case REMOTE_HL_CHECK: /* HC = Check availability of HL commands*/ - _respond(REMOTE_RESP_OK, 0); - break; - case REMOTE_HL_JTAG_DEV: /* HJ for jtag device to use */ - if (i < 4) { - _respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN); - } else { - remote_dp.dp_jd_index = remotehston(2, packet); - _respond(REMOTE_RESP_OK, 0); - } - break; case REMOTE_DP_READ: /* Hd = Read from DP register */ packet += 2; uint16_t addr16 = remotehston(4, packet); diff --git a/src/remote.h b/src/remote.h index 3cfd1b0a..94eee009 100644 --- a/src/remote.h +++ b/src/remote.h @@ -24,6 +24,8 @@ #include #include "general.h" +#define REMOTE_HL_VERSION 1 + /* * Commands to remote end, and responses * ===================================== @@ -86,7 +88,6 @@ /* High level protocol elements */ #define REMOTE_HL_CHECK 'C' -#define REMOTE_HL_JTAG_DEV 'J' #define REMOTE_HL_PACKET 'H' #define REMOTE_DP_READ 'd' #define REMOTE_LOW_ACCESS 'L' @@ -156,24 +157,21 @@ REMOTE_EOM, 0} #define REMOTE_HL_CHECK_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_HL_CHECK, REMOTE_EOM, 0 } -#define REMOTE_HL_JTAG_DEV_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, \ - REMOTE_HL_JTAG_DEV, '%', '0', '2', 'x', REMOTE_EOM, 0 } -#define REMOTE_MEM_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_MEM_READ, \ - HEX_U32(address), HEX_U32(count), REMOTE_EOM, 0 } #define REMOTE_DP_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_DP_READ, \ - 'f', 'f', '%', '0', '4', 'x', REMOTE_EOM, 0 } + '%','0', '2', 'x', 'f', 'f', '%', '0', '4', 'x', REMOTE_EOM, 0 } #define REMOTE_LOW_ACCESS_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_LOW_ACCESS, \ - '%','0', '2', 'x', '%', '0', '4', 'x', HEX_U32(csw), REMOTE_EOM, 0 } + '%','0', '2', 'x', '%','0', '2', 'x', '%', '0', '4', 'x', HEX_U32(csw), REMOTE_EOM, 0 } #define REMOTE_AP_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_READ, \ - '%','0','2','x', '%', '0', '4', 'x', REMOTE_EOM, 0 } + '%','0', '2', 'x', '%','0','2','x', '%', '0', '4', 'x', REMOTE_EOM, 0 } #define REMOTE_AP_WRITE_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_WRITE, \ - '%','0','2','x', '%', '0', '4', 'x', HEX_U32(csw), REMOTE_EOM, 0 } + '%','0', '2', 'x', '%','0','2','x', '%', '0', '4', 'x', HEX_U32(csw), REMOTE_EOM, 0 } #define REMOTE_AP_MEM_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_MEM_READ, \ - '%','0','2','x',HEX_U32(csw), HEX_U32(address), HEX_U32(count), REMOTE_EOM, 0 } + '%','0', '2', 'x', '%','0','2','x',HEX_U32(csw), HEX_U32(address), HEX_U32(count), \ + REMOTE_EOM, 0 } #define REMOTE_AP_MEM_WRITE_SIZED_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_MEM_WRITE_SIZED, \ - '%', '0', '2', 'x', HEX_U32(csw), '%', '0', '2', 'x', HEX_U32(address), HEX_U32(count), 0} + '%','0', '2', 'x', '%', '0', '2', 'x', HEX_U32(csw), '%', '0', '2', 'x', HEX_U32(address), HEX_U32(count), 0} #define REMOTE_MEM_WRITE_SIZED_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_MEM_WRITE_SIZED, \ - '%','0','2','x', HEX_U32(address), HEX_U32(count), 0} + '%','0', '2', 'x', '%','0','2','x', HEX_U32(address), HEX_U32(count), 0} uint64_t remotehston(uint32_t limit, char *s); void remotePacketProcess(uint8_t i, char *packet); From 776861c6a0a34f0fe289ed997b9f60d1b13dcda1 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 19 Oct 2020 18:14:59 +0200 Subject: [PATCH 02/20] Makefile: Fix version.h generation for make all_platforms Same fix as 0ae65cc10fd2. --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 0644791a..9499d8e3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -119,7 +119,7 @@ clean: host_clean all_platforms: $(Q)set -e ;\ - mkdir -p artifacts/$(shell git describe --always) ;\ + mkdir -p artifacts/$(shell git describe --always --dirty --tags) ;\ echo "
    " > artifacts/index.html ;\ for i in platforms/*/Makefile.inc ; do \ export DIRNAME=`dirname $$i` ;\ @@ -140,7 +140,7 @@ all_platforms: fi ;\ done ;\ echo "
" >> artifacts/index.html ;\ - cp artifacts/*.bin artifacts/$(shell git describe --always) + cp artifacts/*.bin artifacts/$(shell git describe --always --dirty --tags) command.c: include/version.h From 73e6b540b23d62d5fe50e1efce4deca08f2b5004 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 22 Oct 2020 12:52:38 +0200 Subject: [PATCH 03/20] command: When debug channel is available, print morse messages readable. --- src/command.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index caaaa57a..032023d0 100644 --- a/src/command.c +++ b/src/command.c @@ -291,8 +291,10 @@ bool cmd_morse(target *t, int argc, char **argv) (void)t; (void)argc; (void)argv; - if(morse_msg) + if(morse_msg) { gdb_outf("%s\n", morse_msg); + DEBUG_WARN("%s\n", morse_msg); + } return true; } From f76a7c4e92f704db5f0f655502875e29ac2651bd Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 22 Oct 2020 12:56:33 +0200 Subject: [PATCH 04/20] adiv5: Release devices after scan. Before, scanning only kept device stopped until POR or attach/detach cycle. --- src/target/adiv5.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index b6990c94..21fcad3f 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -750,6 +750,10 @@ void adiv5_dp_init(ADIv5_DP_t *dp) /* The rest should only be added after checking ROM table */ adiv5_component_probe(ap, ap->base, 0, 0); } + /* We halted at least CortexM for Romtable scan. + * Release the devices now. Attach() will halt them again.*/ + for (target *t = target_list; t; t = t->next) + target_halt_resume(t, false); adiv5_dp_unref(dp); } From 18673d9a56175ce8b3bf1449db0281db622b756b Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 22 Oct 2020 15:38:50 +0200 Subject: [PATCH 05/20] adiv5: Rework DP/AP refcounting. ASAN non longer reports leaks with the STM32H745. --- src/platforms/hosted/platform.c | 2 -- src/platforms/pc/cl_utils.c | 1 + src/target/adiv5.c | 25 +++++++++++-------------- src/target/adiv5_swdp.c | 22 +++++++++------------- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index f1f88b8a..4d2fd9e5 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -352,7 +352,6 @@ int platform_adiv5_swdp_scan(void) if (target_list) return 1; } - free(dp); break; } case BMP_TYPE_CMSIS_DAP: @@ -364,7 +363,6 @@ int platform_adiv5_swdp_scan(void) if (target_list) return 1; } - free(dp); break; } case BMP_TYPE_JLINK: diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 545e102c..7af20b5d 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -494,5 +494,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) target_detach: if (t) target_detach(t); + target_list_free(); return res; } diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 21fcad3f..7190b494 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -263,13 +263,10 @@ static const struct { extern bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base); -static void adiv5_dp_ref(ADIv5_DP_t *dp) -{ - dp->refcnt++; -} - void adiv5_ap_ref(ADIv5_AP_t *ap) { + if (ap->refcnt == 0) + ap->dp->refcnt++; ap->refcnt++; } @@ -404,6 +401,7 @@ static bool cortexm_prepare(ADIv5_AP_t *ap) return true; } +/* Return true if we find a debuggable device.*/ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry) { (void) num_entry; @@ -488,7 +486,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, } /* Probe recursively */ - adiv5_component_probe( + res = adiv5_component_probe( ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET), recursion + 1, i); } @@ -543,15 +541,14 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, cidc_debug_strings[cid_class], cidc_debug_strings[pidr_pn_bits[i].cidc]); } - res = true; switch (pidr_pn_bits[i].arch) { case aa_cortexm: DEBUG_INFO("%s-> cortexm_probe\n", indent + 1); - cortexm_probe(ap); + res = cortexm_probe(ap); break; case aa_cortexa: DEBUG_INFO("\n -> cortexa_probe\n"); - cortexa_probe(ap, addr); + res = cortexa_probe(ap, addr); break; default: DEBUG_INFO("\n"); @@ -598,7 +595,6 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) } memcpy(ap, &tmpap, sizeof(*ap)); - adiv5_dp_ref(dp); ap->csw = adiv5_ap_read(ap, ADIV5_AP_CSW) & ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); @@ -620,7 +616,6 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) void adiv5_dp_init(ADIv5_DP_t *dp) { volatile uint32_t ctrlstat = 0; - adiv5_dp_ref(dp); #if PC_HOSTED == 1 platform_adiv5_dp_defaults(dp); if (!dp->ap_write) @@ -693,6 +688,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp) } } + bool res = false; uint32_t dp_idcode = adiv5_dp_read(dp, ADIV5_DP_IDCODE); if ((dp_idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { /* Read TargetID. Can be done with device in WFI, sleep or reset!*/ @@ -729,7 +725,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp) if (dp->ap_cleanup) dp->ap_cleanup(i); #endif - free(ap); + adiv5_ap_unref(ap); /* FIXME: Should we expect valid APs behind duplicate ones? */ return; } @@ -748,13 +744,14 @@ void adiv5_dp_init(ADIv5_DP_t *dp) */ /* The rest should only be added after checking ROM table */ - adiv5_component_probe(ap, ap->base, 0, 0); + res = adiv5_component_probe(ap, ap->base, 0, 0); + if (!res) + adiv5_ap_unref(ap); } /* We halted at least CortexM for Romtable scan. * Release the devices now. Attach() will halt them again.*/ for (target *t = target_list; t; t = t->next) target_halt_resume(t, false); - adiv5_dp_unref(dp); } #define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \ diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 457b35fa..69c771f9 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -38,21 +38,12 @@ int adiv5_swdp_scan(void) uint32_t ack; target_list_free(); - ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); - dp->dp_jd_index = JTAG_MAX_DEVS; /* Tag for BMP_REMOTE */ - if (!dp) { /* calloc failed: heap exhaustion */ - DEBUG_WARN("calloc: failed in %s\n", __func__); - return -1; - } - #if PC_HOSTED == 1 if (platform_swdptap_init()) { - free(dp); exit(-1); } #else if (swdptap_init()) { - free(dp); return -1; } #endif @@ -71,12 +62,19 @@ int adiv5_swdp_scan(void) * allow the ack to be checked here. */ swd_proc.swdptap_seq_out(0xA5, 8); ack = swd_proc.swdptap_seq_in(3); - if((ack != SWDP_ACK_OK) || swd_proc.swdptap_seq_in_parity(&dp->idcode, 32)) { + 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); - free(dp); return -1; } + 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; @@ -84,8 +82,6 @@ int adiv5_swdp_scan(void) firmware_swdp_error(dp); adiv5_dp_init(dp); - if (!target_list) - free(dp); return target_list?1:0; } From 1f7a7167101d94f1faf00e67e37f07bf956c1800 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 22 Oct 2020 15:48:23 +0200 Subject: [PATCH 06/20] adiv5.c: Run cortexm_prepare on all suspected CortexM instances. Gets all debug units of the second CPU of a STM32H745 visible. --- src/target/adiv5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 7190b494..80cf7daf 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -411,7 +411,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) { /* Maybe caused by a not halted CortexM */ - if (!ap->apsel && ((ap->idr & 0xf) == ARM_AP_TYPE_AHB)) { + if ((ap->idr & 0xf) == ARM_AP_TYPE_AHB) { if (!cortexm_prepare(ap)) return false; /* Halting failed! */ /* CPU now halted, read cidr again. */ From 99142d1c0ead9695dac0d171510e29094bc4f921 Mon Sep 17 00:00:00 2001 From: Stoyan Shopov Date: Thu, 29 Oct 2020 22:57:33 +0200 Subject: [PATCH 07/20] Add documentation details for building PC-hosted BMP in msys2. --- src/platforms/hosted/Readme.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/platforms/hosted/Readme.md b/src/platforms/hosted/Readme.md index a3f31c43..13477ddd 100644 --- a/src/platforms/hosted/Readme.md +++ b/src/platforms/hosted/Readme.md @@ -38,9 +38,11 @@ blackmagic -V .bin ``` blackmagic -h" ``` -## Used libraries: +## Used shared libraries: ### libusb ### libftdi, for FTDI support + +## Other used libraries: ### hidapi-libusb, for CMSIS-DAP support ## Compiling on windows @@ -51,8 +53,21 @@ needed. For running, libftdi1.dll and libusb-1.0.dll are needed and the executable must be able to find them. Mingw on cygwin does not provide a libftdi package yet. -To prepare libusb access to the ftdi device, run zadig https://zadig.akeo.ie/. -Choose WinUSB(libusb-1.0) for the BMP Ftdi device. +PC-hosted BMP for windows can also be built with [MSYS2](https://www.msys2.org/), +in windows. Make sure to use the `mingw64` shell from msys2, otherwise, +you may get compilation errors. You will need to install the libusb +and libftdi libraries, and have the correct mingw compiler. +You can use these commands to install dependencies, and build PC-hosted BMP +from a mingw64 shell, from within the `src` directory: +``` +pacman -S mingw-w64-x86_64-libusb --needed +pacman -S mingw-w64-x86_64-libftdi --needed +pacman -S mingw-w64-x86_64-gcc --needed +PROBE_HOST=hosted make +``` + +To prepare libusb access to the ftdi/stlink/jlink/cmsis-dap devices, run zadig +https://zadig.akeo.ie/. Choose WinUSB(libusb-1.0). Running cygwin/blackmagic in a cygwin console, the program does not react on ^C. In another console, run "ps ax" to find the WINPID of the process From d75f3124b9b4c774ec2ea9d90c68cbff764e55f8 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 1 Nov 2020 11:54:27 +0100 Subject: [PATCH 08/20] ftdi_bmp.c: Reapply fix from #715: Check for libftdi 1.5 --- src/platforms/hosted/ftdi_bmp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/platforms/hosted/ftdi_bmp.c b/src/platforms/hosted/ftdi_bmp.c index f4f4fe47..acf9ed4f 100644 --- a/src/platforms/hosted/ftdi_bmp.c +++ b/src/platforms/hosted/ftdi_bmp.c @@ -341,23 +341,27 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) goto error_2; } assert(ftdic != NULL); - err = ftdi_usb_purge_buffers(ftdic); +#ifdef _Ftdi_Pragma + err = ftdi_tcioflush(ftdic); +#else + err = ftdi_usb_purge_buffers(ftdic); +#endif if (err != 0) { - fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n", + DEBUG_WARN("ftdi_tcioflush(ftdi_usb_purge_buffer): %d: %s\n", err, ftdi_get_error_string(ftdic)); goto error_2; } /* Reset MPSSE controller. */ err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET); if (err != 0) { - fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", + DEBUG_WARN("ftdi_set_bitmode: %d: %s\n", err, ftdi_get_error_string(ftdic)); goto error_2; } /* Enable MPSSE controller. Pin directions are set later.*/ err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE); if (err != 0) { - fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", + DEBUG_WARN("ftdi_set_bitmode: %d: %s\n", err, ftdi_get_error_string(ftdic)); goto error_2; } From 2c33cde63fe779d3019fe8f63dd4420cb960bbfe Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 1 Nov 2020 21:26:28 +0100 Subject: [PATCH 09/20] cortexm.c/cortexm_halt_resume: Add some clock cycles to always get CPU going (#768) --- src/target/cortexm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 09657353..96004cff 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -835,6 +835,8 @@ static void cortexm_halt_resume(target *t, bool step) target_mem_write32(t, CORTEXM_ICIALLU, 0); target_mem_write32(t, CORTEXM_DHCSR, dhcsr); + /* Add some clock cycles to get the CPU running again.*/ + target_mem_read32(t, 0); } static int cortexm_fault_unwind(target *t) From f18be6ef7afe73eebbc3354161e083d0004c22bf Mon Sep 17 00:00:00 2001 From: jbuonagurio Date: Fri, 6 Nov 2020 03:42:52 -0500 Subject: [PATCH 10/20] Add support for Kinetis K12 and placeholders for other K-series MCUs --- src/target/cortexm.c | 6 +++-- src/target/kinetis.c | 64 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 96004cff..18315730 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -435,12 +435,14 @@ bool cortexm_probe(ADIv5_AP_t *ap) } if (ap->ap_partno == 0x4c3) /* Cortex-M3 ROM */ PROBE(stm32f1_probe); /* Care for STM32F1 clones */ - else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */ + else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */ PROBE(lpc11xx_probe); /* LPC24C11 */ PROBE(lpc43xx_probe); } - else if (ap->ap_partno == 0x4c4) /* Cortex-M4 ROM */ + else if (ap->ap_partno == 0x4c4) { /* Cortex-M4 ROM */ PROBE(lpc43xx_probe); + PROBE(kinetis_probe); /* Older K-series */ + } /* Info on PIDR of these parts wanted! */ PROBE(sam3x_probe); PROBE(lpc15xx_probe); diff --git a/src/target/kinetis.c b/src/target/kinetis.c index ef88999d..3b6abd9f 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -196,7 +196,7 @@ bool kinetis_probe(target *t) kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); break; case 0x271: - switch((sdid>>16)&0x0f){ + switch((sdid >> 16) & 0x0f) { case 4: t->driver = "KL27x32"; target_add_ram(t, 0x1ffff800, 0x0800); @@ -214,7 +214,7 @@ bool kinetis_probe(target *t) } break; case 0x021: /* KL02 family */ - switch((sdid>>16) & 0x0f){ + switch((sdid >> 16) & 0x0f) { case 3: t->driver = "KL02x32"; target_add_ram(t, 0x1FFFFC00, 0x400); @@ -235,7 +235,7 @@ bool kinetis_probe(target *t) break; default: return false; - } + } break; case 0x031: /* KL03 family */ t->driver = "KL03"; @@ -261,6 +261,64 @@ bool kinetis_probe(target *t) kl_gen_add_flash(t, 0, 0x80000, 0x1000, K64_WRITE_LEN); kl_gen_add_flash(t, 0x80000, 0x80000, 0x1000, K64_WRITE_LEN); break; + case 0x000: /* Older K-series */ + switch(sdid & 0xff0) { + case 0x000: /* K10 Family, DIEID=0x0 */ + case 0x080: /* K10 Family, DIEID=0x1 */ + case 0x100: /* K10 Family, DIEID=0x2 */ + case 0x180: /* K10 Family, DIEID=0x3 */ + case 0x220: /* K11 Family, DIEID=0x4 */ + return false; + case 0x200: /* K12 Family, DIEID=0x4 */ + switch((fcfg1 >> 24) & 0x0f) { + /* K12 Sub-Family Reference Manual, K12P80M50SF4RM, Rev. 4, February 2013 */ + case 0x7: + t->driver = "MK12DX128Vxx5"; + target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ + target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ + kl_gen_add_flash(t, 0x00000000, 0x00020000, 0x800, KL_WRITE_LEN); /* P-Flash, 128 KB, 2 KB Sectors */ + kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ + break; + case 0x9: + t->driver = "MK12DX256Vxx5"; + target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ + target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ + kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ + break; + case 0xb: + t->driver = "MK12DN512Vxx5"; + target_add_ram(t, 0x1fff8000, 0x00008000); /* SRAM_L, 32 KB */ + target_add_ram(t, 0x20000000, 0x00008000); /* SRAM_H, 32 KB */ + kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kl_gen_add_flash(t, 0x00040000, 0x00040000, 0x800, KL_WRITE_LEN); /* FlexNVM, 256 KB, 2 KB Sectors */ + break; + default: + return false; + } + break; + case 0x010: /* K20 Family, DIEID=0x0 */ + case 0x090: /* K20 Family, DIEID=0x1 */ + case 0x110: /* K20 Family, DIEID=0x2 */ + case 0x190: /* K20 Family, DIEID=0x3 */ + case 0x230: /* K21 Family, DIEID=0x4 */ + case 0x330: /* K21 Family, DIEID=0x6 */ + case 0x210: /* K22 Family, DIEID=0x4 */ + case 0x310: /* K22 Family, DIEID=0x6 */ + case 0x0a0: /* K30 Family, DIEID=0x1 */ + case 0x120: /* K30 Family, DIEID=0x2 */ + case 0x0b0: /* K40 Family, DIEID=0x1 */ + case 0x130: /* K40 Family, DIEID=0x2 */ + case 0x0e0: /* K50 Family, DIEID=0x1 */ + case 0x0f0: /* K51 Family, DIEID=0x1 */ + case 0x170: /* K53 Family, DIEID=0x2 */ + case 0x140: /* K60 Family, DIEID=0x2 */ + case 0x1c0: /* K60 Family, DIEID=0x3 */ + case 0x1d0: /* K70 Family, DIEID=0x3 */ + default: + return false; + } + break; default: return false; } From e9c02296f29de18a56ea109384fb9c375c072700 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 14 Nov 2020 14:30:13 +0800 Subject: [PATCH 11/20] target: kinetis: add S32K118 This adds support for the NXP S32K118. This is an automotive-grade part that is derived from the Kinetis line, so it has a very similar interface to other parts in the family. Signed-off-by: Sean Cross --- src/target/kinetis.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 3b6abd9f..442eac8b 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -319,6 +319,13 @@ bool kinetis_probe(target *t) return false; } break; + case 0x118: /* S32K118 */ + t->driver = "S32K118"; + target_add_ram(t, 0x1ffffc00, 0x00000400); /* SRAM_L, 1 KB */ + target_add_ram(t, 0x20000000, 0x00005800); /* SRAM_H, 22 KB */ + kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, K64_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kl_gen_add_flash(t, 0x10000000, 0x00008000, 0x800, K64_WRITE_LEN); /* FlexNVM, 32 KB, 2 KB Sectors */ + break; default: return false; } From 35bcb4f7c60ce711977f3baa08fbe67fe6206d17 Mon Sep 17 00:00:00 2001 From: Noah Pendleton Date: Tue, 24 Nov 2020 15:18:21 -0500 Subject: [PATCH 12/20] Switch on the lpc546xx target Enable the lpc546xx target. Tested on the LPCXpresso54628 dev board, able to flash and debug. --- src/target/cortexm.c | 1 + src/target/lpc546xx.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 18315730..36ebf5bd 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -441,6 +441,7 @@ bool cortexm_probe(ADIv5_AP_t *ap) } else if (ap->ap_partno == 0x4c4) { /* Cortex-M4 ROM */ PROBE(lpc43xx_probe); + PROBE(lpc546xx_probe); PROBE(kinetis_probe); /* Older K-series */ } /* Info on PIDR of these parts wanted! */ diff --git a/src/target/lpc546xx.c b/src/target/lpc546xx.c index fff18bf6..1e0ad930 100644 --- a/src/target/lpc546xx.c +++ b/src/target/lpc546xx.c @@ -140,7 +140,7 @@ bool lpc546xx_probe(target *t) target_add_commands(t, lpc546xx_cmd_list, "Lpc546xx"); t->target_options |= CORTEXM_TOPT_INHIBIT_SRST; - return false; + return true; } /* Reset all major systems _except_ debug */ From 80154c5c7a62a981efdf0f33658b349a1af71e17 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 24 Oct 2020 18:08:07 +0200 Subject: [PATCH 13/20] adiv5_swdp: Fix more memory leak. --- src/platforms/hosted/jlink_adiv5_swdp.c | 8 +++++--- src/platforms/hosted/platform.c | 2 ++ src/target/adiv5_swdp.c | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/platforms/hosted/jlink_adiv5_swdp.c b/src/platforms/hosted/jlink_adiv5_swdp.c index b9deabb2..6895b9ad 100644 --- a/src/platforms/hosted/jlink_adiv5_swdp.c +++ b/src/platforms/hosted/jlink_adiv5_swdp.c @@ -124,9 +124,6 @@ int jlink_swdp_scan(bmp_info_t *info) { swdptap_init(info); target_list_free(); - ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); - if (!dp) /* calloc failed: heap exhaustion */ - return 0; uint8_t cmd[44]; cmd[0] = CMD_HW_JTAG3; cmd[1] = 0; @@ -178,6 +175,9 @@ int jlink_swdp_scan(bmp_info_t *info) DEBUG_WARN( "Line reset failed\n"); return 0; } + ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); + if (!dp) /* calloc failed: heap exhaustion */ + return 0; dp->idcode = jlink_adiv5_swdp_low_access(dp, 1, ADIV5_DP_IDCODE, 0); dp->dp_read = jlink_adiv5_swdp_read; dp->error = jlink_adiv5_swdp_error; @@ -186,6 +186,8 @@ int jlink_swdp_scan(bmp_info_t *info) jlink_adiv5_swdp_error(dp); adiv5_dp_init(dp); + if (!target_list) + free(dp); return target_list?1:0; } diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 4d2fd9e5..f1f88b8a 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -352,6 +352,7 @@ int platform_adiv5_swdp_scan(void) if (target_list) return 1; } + free(dp); break; } case BMP_TYPE_CMSIS_DAP: @@ -363,6 +364,7 @@ int platform_adiv5_swdp_scan(void) if (target_list) return 1; } + free(dp); break; } case BMP_TYPE_JLINK: diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 69c771f9..4351dd17 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -82,6 +82,8 @@ int adiv5_swdp_scan(void) firmware_swdp_error(dp); adiv5_dp_init(dp); + if (!target_list) + free(dp); return target_list?1:0; } From f71e18948aba7f1742dfe7d64ab4516209c03a2a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 24 Oct 2020 20:35:07 +0200 Subject: [PATCH 14/20] GPIO for SWD: Slow down edges on more platforms. --- src/platforms/stlink/platform.c | 8 ++++---- src/platforms/stlink/platform.h | 2 +- src/platforms/swlink/platform.c | 8 ++++---- src/platforms/swlink/platform.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 54b80461..a38b0a7f 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -61,11 +61,11 @@ void platform_init(void) srst_pin = SRST_PIN_V2; } /* Setup GPIO ports */ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_INPUT_FLOAT, TMS_PIN); - gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN); - gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); platform_srst_set_val(false); @@ -90,7 +90,7 @@ void platform_init(void) void platform_srst_set_val(bool assert) { if (assert) { - gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, srst_pin); gpio_clear(SRST_PORT, srst_pin); } else { diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 280d0aac..99e3555f 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -78,7 +78,7 @@ int usbuart_debug_write(const char *buf, size_t len); # define SWD_CR_MULT (1 << ((14 - 8) << 2)) #define TMS_SET_MODE() \ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); #define SWDIO_MODE_FLOAT() do { \ uint32_t cr = SWD_CR; \ diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 18efbf3a..a11ea55b 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -67,11 +67,11 @@ void platform_init(void) data |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF; AFIO_MAPR = data; /* Setup JTAG GPIO ports */ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_INPUT_FLOAT, TMS_PIN); - gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN); - gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); gpio_set_mode(TDO_PORT, GPIO_MODE_INPUT, @@ -118,7 +118,7 @@ void platform_srst_set_val(bool assert) { /* We reuse JSRST as SRST.*/ if (assert) { - gpio_set_mode(JRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(JRST_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, JRST_PIN); /* Wait until requested value is active.*/ while (gpio_get(JRST_PORT, JRST_PIN)) diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 50baf059..aadf0428 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -72,7 +72,7 @@ int usbuart_debug_write(const char *buf, size_t len); # define SWD_CR_MULT (1 << ((13 - 8) << 2)) #define TMS_SET_MODE() \ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); #define SWDIO_MODE_FLOAT() do { \ uint32_t cr = SWD_CR; \ From e68dd2581371230f97d00b2a6afe63afd0a2e5a9 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 25 Oct 2020 12:00:59 +0100 Subject: [PATCH 15/20] cl_utils: Clarify -d option is BMP/firmware only and deprecate -d. --- src/platforms/pc/cl_utils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 7af20b5d..b1471754 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -123,7 +123,7 @@ static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt) DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n"); DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n"); DEBUG_WARN("Probe selection arguments:\n"); - DEBUG_WARN("\t-d \"path\"\t: Use serial device at \"path\"\n"); + DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at \"path\"(Deprecated)\n"); DEBUG_WARN("\t-P \t: Use debugger found at position \n"); DEBUG_WARN("\t-n \t: Use target device found at position \n"); DEBUG_WARN("\t-s \"serial\"\t: Use dongle with (partial) " @@ -189,6 +189,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->external_resistor_swd = true; break; case 'd': + DEBUG_WARN("Deprecated!\n"); if (optarg) opt->opt_device = optarg; break; From 824a1d8abc2e77b7de808de38e9a621b1db9ce74 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 25 Oct 2020 12:39:41 +0100 Subject: [PATCH 16/20] hosted/find_debuggers: Do not check hubs. Print class of devices unable to open. --- src/platforms/hosted/platform.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index f1f88b8a..d37c635a 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -111,12 +111,16 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) libusb_free_device_list(devs, 1); continue; } + /* Exclude hubs from testing. Probably more classes could be excluded here!*/ + if (desc.bDeviceClass == LIBUSB_CLASS_HUB) { + continue; + } libusb_device_handle *handle; res = libusb_open(dev, &handle); if (res != LIBUSB_SUCCESS) { if (!access_problems) { - DEBUG_INFO("INFO: Open USB %04x:%04x failed\n", - desc.idVendor, desc.idProduct); + DEBUG_INFO("INFO: Open USB %04x:%04x class %2x failed\n", + desc.idVendor, desc.idProduct, desc.bDeviceClass); access_problems = true; } continue; From 653d486ee24a24e70803b0cf0b8981c73df472b2 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 5 Nov 2020 18:44:04 +0100 Subject: [PATCH 17/20] cortexm: Store CPUID in target structure. --- src/target/cortexm.c | 32 ++++++++++++++------------------ src/target/cortexm.h | 13 +++++++++++++ src/target/lpc17xx.c | 6 +----- src/target/lpc43xx.c | 10 ++++------ src/target/stm32f4.c | 4 +--- src/target/target_internal.h | 3 ++- 6 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 36ebf5bd..452fe2d2 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -297,41 +297,37 @@ bool cortexm_probe(ADIv5_AP_t *ap) * that is, the actual values are found in the Technical Reference Manual * for each Cortex-M core. */ - uint32_t cpuid = target_mem_read32(t, CORTEXM_CPUID); - uint16_t partno = (cpuid >> 4) & 0xfff; - - switch (partno) { - case 0xd21: + t->cpuid = target_mem_read32(t, CORTEXM_CPUID); + uint32_t cpuid_partno = t->cpuid & CPUID_PARTNO_MASK; + switch (cpuid_partno) { + case CORTEX_M33: t->core = "M33"; break; - - case 0xd20: + case CORTEX_M23: t->core = "M23"; break; - - case 0xc23: + case CORTEX_M3: t->core = "M3"; break; - - case 0xc24: + case CORTEX_M4: t->core = "M4"; break; - - case 0xc27: + case CORTEX_M7: t->core = "M7"; - if ((((cpuid >> 20) & 0xf) == 0) && (((cpuid >> 0) & 0xf) < 2)) { + if (((t->cpuid & CPUID_REVISION_MASK) == 0) && + (t->cpuid & CPUID_PATCH_MASK) < 2) { DEBUG_WARN("Silicon bug: Single stepping will enter pending " "exception handler with this M7 core revision!\n"); } break; - - case 0xc60: + case CORTEX_M0P: t->core = "M0+"; break; - - case 0xc20: + case CORTEX_M0: t->core = "M0"; break; + default: + DEBUG_WARN("Unexpected CortexM CPUID partno %04x\n", cpuid_partno); } t->attach = cortexm_attach; diff --git a/src/target/cortexm.h b/src/target/cortexm.h index f230e0b5..82087859 100644 --- a/src/target/cortexm.h +++ b/src/target/cortexm.h @@ -171,6 +171,19 @@ extern long cortexm_wait_timeout; #define CORTEXM_TOPT_INHIBIT_SRST (1 << 2) +enum cortexm_types { + CORTEX_M0 = 0xc200, + CORTEX_M0P = 0xc600, + CORTEX_M3 = 0xc230, + CORTEX_M4 = 0xc240, + CORTEX_M7 = 0xc270, + CORTEX_M23 = 0xd200, + CORTEX_M33 = 0xd210, +}; +#define CPUID_PARTNO_MASK 0xfff0 +#define CPUID_REVISION_MASK 0x00f00000 +#define CPUID_PATCH_MASK 0xf + bool cortexm_probe(ADIv5_AP_t *ap); ADIv5_AP_t *cortexm_ap(target *t); diff --git a/src/target/lpc17xx.c b/src/target/lpc17xx.c index d4101816..f62e3818 100644 --- a/src/target/lpc17xx.c +++ b/src/target/lpc17xx.c @@ -32,9 +32,6 @@ #define IAP_ENTRYPOINT 0x1FFF1FF1 #define IAP_RAM_BASE 0x10000000 -#define ARM_CPUID 0xE000ED00 -#define CORTEX_M3_CPUID 0x412FC230 // Cortex-M3 r2p0 -#define CORTEX_M3_CPUID_MASK 0xFF00FFF0 #define MEMMAP 0x400FC040 #define LPC17xx_JTAG_IDCODE 0x4BA00477 #define LPC17xx_SWDP_IDCODE 0x2BA01477 @@ -82,8 +79,7 @@ lpc17xx_probe(target *t) return false; } - uint32_t cpuid = target_mem_read32(t, ARM_CPUID); - if (((cpuid & CORTEX_M3_CPUID_MASK) == (CORTEX_M3_CPUID & CORTEX_M3_CPUID_MASK))) { + if ((t->cpuid & CPUID_PARTNO_MASK) == CORTEX_M3) { /* * Now that we're sure it's a Cortex-M3, we need to halt the * target and make an IAP call to get the part number. diff --git a/src/target/lpc43xx.c b/src/target/lpc43xx.c index a1fb2145..c5a837dc 100644 --- a/src/target/lpc43xx.c +++ b/src/target/lpc43xx.c @@ -25,7 +25,6 @@ #include "lpc_common.h" #define LPC43XX_CHIPID 0x40043200 -#define ARM_CPUID 0xE000ED00 #define IAP_ENTRYPOINT_LOCATION 0x10400100 @@ -80,19 +79,18 @@ void lpc43xx_add_flash(target *t, uint32_t iap_entry, bool lpc43xx_probe(target *t) { - uint32_t chipid, cpuid; + uint32_t chipid; uint32_t iap_entry; chipid = target_mem_read32(t, LPC43XX_CHIPID); - cpuid = target_mem_read32(t, ARM_CPUID); switch(chipid) { case 0x4906002B: /* Parts with on-chip flash */ case 0x7906002B: /* LM43S?? - Undocumented? */ - switch (cpuid & 0xFF00FFF0) { + switch (t->cpuid & 0xFF00FFF0) { case 0x4100C240: t->driver = "LPC43xx Cortex-M4"; - if (cpuid == 0x410FC241) + if (t->cpuid == 0x410FC241) { /* LPC4337 */ iap_entry = target_mem_read32(t, @@ -121,7 +119,7 @@ bool lpc43xx_probe(target *t) return true; case 0x5906002B: /* Flashless parts */ case 0x6906002B: - switch (cpuid & 0xFF00FFF0) { + switch (t->cpuid & 0xFF00FFF0) { case 0x4100C240: t->driver = "LPC43xx Cortex-M4"; break; diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 33691c7b..f51ce44b 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -106,7 +106,6 @@ static int stm32f4_flash_write(struct target_flash *f, #define DBGMCU_IDCODE 0xE0042000 #define DBGMCU_CR 0xE0042004 #define DBG_SLEEP (1 << 0) -#define ARM_CPUID 0xE000ED00 #define AXIM_BASE 0x8000000 #define ITCM_BASE 0x0200000 @@ -208,8 +207,7 @@ bool stm32f4_probe(target *t) /* F405 revision A have a wrong IDCODE, use ARM_CPUID to make the * distinction with F205. Revision is also wrong (0x2000 instead * of 0x1000). See F40x/F41x errata. */ - uint32_t cpuid = target_mem_read32(t, ARM_CPUID); - if ((cpuid & 0xFFF0) == 0xC240) + if ((t->cpuid & 0xFFF0) == CORTEX_M4) t->idcode = ID_STM32F40X; } switch(t->idcode) { diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 66ff2019..58475bca 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -120,7 +120,8 @@ struct target_s { /* Other stuff */ const char *driver; - const char *core; + uint32_t cpuid; + char *core; char cmdline[MAX_CMDLINE]; target_addr heapinfo[4]; struct target_command_s *commands; From d78d7838d32f38a7f5133007123f111845c07bc5 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 5 Nov 2020 18:53:44 +0100 Subject: [PATCH 18/20] stm32f1: Always read DBGMCU_IDCODE for t->idcode (#770) At least STM32F042 has 0x440 as romtable partno vs 0x445 as DBGMCU_IDCODE. Thanks to Andrey Melnikov(aam335) for pointing out! --- src/target/stm32f1.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/target/stm32f1.c b/src/target/stm32f1.c index 731973d1..8c1fd429 100644 --- a/src/target/stm32f1.c +++ b/src/target/stm32f1.c @@ -118,7 +118,10 @@ static void stm32f1_add_flash(target *t, bool stm32f1_probe(target *t) { - if (t->t_designer == AP_DESIGNER_ARM) + uint16_t stored_idcode = t->idcode; + if ((t->cpuid & CPUID_PARTNO_MASK) == CORTEX_M0) + t->idcode = target_mem_read32(t, DBGMCU_IDCODE_F0) & 0xfff; + else t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; size_t flash_size; size_t block_size = 0x400; @@ -191,6 +194,7 @@ bool stm32f1_probe(target *t) block_size = 0x800; break; default: /* NONE */ + t->idcode = stored_idcode; return false; } From 9ac5adfcef94f04f3c1ddedcaf3b3d5b2c0338c4 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 7 Nov 2020 15:44:16 +0100 Subject: [PATCH 19/20] adiv5: Additional decoding. --- src/target/adiv5.c | 5 +++++ src/target/cortexm.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 80cf7daf..9f7a7ccc 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -608,6 +608,8 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG); DEBUG_INFO("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08" PRIx32 " CSW=%08"PRIx32"\n", apsel, ap->idr, cfg, ap->base, ap->csw); + DEBUG_INFO("AP#0 IDR = 0x%08" PRIx32 " (AHB-AP var%x rev%x)\n", + ap->idr, (ap->idr >> 4) & 0xf, ap->idr >> 28); #endif adiv5_ap_ref(ap); return ap; @@ -615,6 +617,9 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) void adiv5_dp_init(ADIv5_DP_t *dp) { + DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%d %srev%d)\n", dp->idcode, + (dp->idcode >> 12) & 0xf, + (dp->idcode & 0x10000) ? "MINDP " : "", dp->idcode >> 28); volatile uint32_t ctrlstat = 0; #if PC_HOSTED == 1 platform_adiv5_dp_defaults(dp); diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 452fe2d2..99252761 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -329,6 +329,9 @@ bool cortexm_probe(ADIv5_AP_t *ap) default: DEBUG_WARN("Unexpected CortexM CPUID partno %04x\n", cpuid_partno); } + DEBUG_INFO("CPUID 0x%08" PRIx32 " (%s var %x rev %x)\n", t->cpuid, + t->core, (t->cpuid & CPUID_REVISION_MASK) >> 20, + t->cpuid & CPUID_PATCH_MASK); t->attach = cortexm_attach; t->detach = cortexm_detach; From cda83d308490738b54df0405cca3c0c048809664 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 7 Nov 2020 17:43:35 +0100 Subject: [PATCH 20/20] Fix memleaks. Happened e.g. when Stlink could not enter debug or when cortexm_prepare timed out. --- src/platforms/hosted/platform.c | 8 +++++-- src/target/adiv5.c | 40 ++++++++++++++++----------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index d37c635a..a0fe7744 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -351,7 +351,9 @@ int platform_adiv5_swdp_scan(void) { target_list_free(); ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); - if (!stlink_enter_debug_swd(&info, dp)) { + if (stlink_enter_debug_swd(&info, dp)) { + free(dp); + } else { adiv5_dp_init(dp); if (target_list) return 1; @@ -363,7 +365,9 @@ int platform_adiv5_swdp_scan(void) { target_list_free(); ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); - if (!dap_enter_debug_swd(dp)) { + if (dap_enter_debug_swd(dp)) { + free(dp); + } else { adiv5_dp_init(dp); if (target_list) return 1; diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 9f7a7ccc..cf2983d6 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -402,23 +402,22 @@ static bool cortexm_prepare(ADIv5_AP_t *ap) } /* Return true if we find a debuggable device.*/ -static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry) +static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry) { (void) num_entry; addr &= 0xfffff000; /* Mask out base address */ if (addr == 0) /* No rom table on this AP */ - return false; + return; uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) { /* Maybe caused by a not halted CortexM */ if ((ap->idr & 0xf) == ARM_AP_TYPE_AHB) { if (!cortexm_prepare(ap)) - return false; /* Halting failed! */ + return; /* Halting failed! */ /* CPU now halted, read cidr again. */ cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); } } - bool res = false; #if defined(ENABLE_DEBUG) char indent[recursion + 1]; @@ -428,7 +427,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, if (adiv5_dp_error(ap->dp)) { DEBUG_WARN("%sFault reading ID registers\n", indent); - return false; + return; } /* CIDR preamble sanity check */ @@ -436,7 +435,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, DEBUG_WARN("%s%d 0x%08" PRIx32": 0x%08" PRIx32 " <- does not match preamble (0x%X)\n", indent + 1, num_entry, addr, cidr, CID_PREAMBLE); - return false; + return; } uint64_t pidr = adiv5_ap_read_pidr(ap, addr); @@ -463,10 +462,8 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, if (recursion == 0) { ap->ap_designer = designer; ap->ap_partno = partno; - if ((ap->ap_designer == AP_DESIGNER_ATMEL) && (ap->ap_partno == 0xcd0)) { + if ((ap->ap_designer == AP_DESIGNER_ATMEL) && (ap->ap_partno == 0xcd0)) cortexm_probe(ap); - return true; - } } for (int i = 0; i < 960; i++) { adiv5_dp_error(ap->dp); @@ -486,7 +483,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, } /* Probe recursively */ - res = adiv5_component_probe( + adiv5_component_probe( ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET), recursion + 1, i); } @@ -499,7 +496,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, DEBUG_WARN("%s0x%" PRIx32 ": 0x%02" PRIx32 "%08" PRIx32 " <- does not match ARM JEP-106\n", indent, addr, (uint32_t)(pidr >> 32), (uint32_t)pidr); - return false; + return; } /* ADIv6: For CoreSight components, read DEVTYPE and ARCHID */ @@ -544,11 +541,11 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, switch (pidr_pn_bits[i].arch) { case aa_cortexm: DEBUG_INFO("%s-> cortexm_probe\n", indent + 1); - res = cortexm_probe(ap); + cortexm_probe(ap); break; case aa_cortexa: DEBUG_INFO("\n -> cortexa_probe\n"); - res = cortexa_probe(ap, addr); + cortexa_probe(ap, addr); break; default: DEBUG_INFO("\n"); @@ -564,7 +561,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, (uint32_t)(pidr >> 32), (uint32_t)pidr, dev_type, arch_id); } } - return res; + return; } ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) @@ -663,6 +660,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp) break; if (platform_timeout_is_expired(&timeout)) { DEBUG_INFO("DEBUG Power-Up failed\n"); + free(dp); /* No AP that referenced this DP so long*/ return; } } @@ -693,7 +691,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp) } } - bool res = false; uint32_t dp_idcode = adiv5_dp_read(dp, ADIV5_DP_IDCODE); if ((dp_idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { /* Read TargetID. Can be done with device in WFI, sleep or reset!*/ @@ -705,6 +702,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp) /* Probe for APs on this DP */ uint32_t last_base = 0; int void_aps = 0; + dp->refcnt++; for(int i = 0; (i < 256) && (void_aps < 8); i++) { ADIv5_AP_t *ap = NULL; #if PC_HOSTED == 1 @@ -719,10 +717,12 @@ void adiv5_dp_init(ADIv5_DP_t *dp) if (dp->ap_cleanup) dp->ap_cleanup(i); #endif - if (i == 0) + if (i == 0) { + adiv5_dp_unref(dp); return; - else + } else { continue; + } } if (ap->base == last_base) { DEBUG_WARN("AP %d: Duplicate base\n", i); @@ -749,14 +749,14 @@ void adiv5_dp_init(ADIv5_DP_t *dp) */ /* The rest should only be added after checking ROM table */ - res = adiv5_component_probe(ap, ap->base, 0, 0); - if (!res) - adiv5_ap_unref(ap); + adiv5_component_probe(ap, ap->base, 0, 0); + adiv5_ap_unref(ap); } /* We halted at least CortexM for Romtable scan. * Release the devices now. Attach() will halt them again.*/ for (target *t = target_list; t; t = t->next) target_halt_resume(t, false); + adiv5_dp_unref(dp); } #define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \