From e1a928beb1210d10e862a6eb782e8836337b9665 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 7 Sep 2021 22:58:21 +0200 Subject: [PATCH 01/31] Fixes to compile with gcc11 #925 Target code changes are pure for formal correctness and not tested! --- src/platforms/hosted/bmp_hosted.h | 6 +++--- src/target/kinetis.c | 6 +++--- src/target/nxpke04.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/platforms/hosted/bmp_hosted.h b/src/platforms/hosted/bmp_hosted.h index fb6b7cfe..fe4ce0be 100644 --- a/src/platforms/hosted/bmp_hosted.h +++ b/src/platforms/hosted/bmp_hosted.h @@ -28,9 +28,9 @@ typedef struct bmp_info_s { bmp_type_t bmp_type; char dev; char serial[64]; - char manufacturer[128]; - char product[128]; - char version[128]; + char manufacturer[512]; + char product[256]; + char version[256]; bool is_jtag; #if HOSTED_BMP_ONLY != 1 libusb_context *libusb_ctx; diff --git a/src/target/kinetis.c b/src/target/kinetis.c index de400d06..7ac9ffa5 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -486,10 +486,10 @@ static int kl_gen_flash_done(struct target_flash *f) kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, FLASH_SECURITY_BYTE_ADDRESS - 4, (uint8_t*)vals); } else { - uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); - val = (val & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; + uint32_t vals[2] = {target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS), 0}; + vals[0] = (vals[0] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, - FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&val); + FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&vals); } return 0; diff --git a/src/target/nxpke04.c b/src/target/nxpke04.c index c577fc2c..4ba642d1 100644 --- a/src/target/nxpke04.c +++ b/src/target/nxpke04.c @@ -373,10 +373,10 @@ static int ke04_flash_done(struct target_flash *f) /* Load the security byte from its field */ /* Note: Cumulative programming is not allowed according to the RM */ - uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_WORD_ADDRESS); - val = (val & 0xff00ffff) | (FLASH_SECURITY_BYTE_UNSECURED << 16); + uint32_t vals[2] = {target_mem_read32(f->t, FLASH_SECURITY_WORD_ADDRESS), 0}; + vals[0] = (vals[0] & 0xff00ffff) | (FLASH_SECURITY_BYTE_UNSECURED << 16); ke04_command(f->t, CMD_PROGRAM_FLASH_32, - FLASH_SECURITY_WORD_ADDRESS, (uint8_t *)&val); + FLASH_SECURITY_WORD_ADDRESS, (uint8_t *)&vals); return 0; } From 7307f086c6425ee8a91fa2c3cd69c210a3cd165d Mon Sep 17 00:00:00 2001 From: SG Date: Sat, 30 Oct 2021 21:01:06 +1000 Subject: [PATCH 02/31] Support for STM32WB55 (#942) * add STM32WB55 support --- src/target/stm32l4.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index 3d0e8a27..9ff64532 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -59,6 +59,7 @@ static int stm32l4_flash_write(struct target_flash *f, #define L4_FPEC_BASE 0x40022000 #define L5_FPEC_BASE 0x40022000 #define WL_FPEC_BASE 0x58004000 +#define WB_FPEC_BASE 0x58004000 #define L5_FLASH_OPTR_TZEN (1 << 31) @@ -141,6 +142,7 @@ enum ID_STM32L4 { ID_STM32G49 = 0x479u, /* RM0440, Rev.6 */ ID_STM32L55 = 0x472u, /* RM0438, Rev.4 */ ID_STM32WLXX = 0x497u, /* RM0461, Rev.3, RM453, Rev.1 */ + ID_STM32WBXX = 0x495u, /* RM0434, Rev.9 */ }; enum FAM_STM32L4 { @@ -192,6 +194,15 @@ static const uint32_t stm32wl_flash_regs_map[FLASH_REGS_COUNT] = { L4_FLASH_SIZE_REG, /* FLASHSIZE */ }; +static const uint32_t stm32wb_flash_regs_map[FLASH_REGS_COUNT] = { + WB_FPEC_BASE + 0x08, /* KEYR */ + WB_FPEC_BASE + 0x0c, /* OPTKEYR */ + WB_FPEC_BASE + 0x10, /* SR */ + WB_FPEC_BASE + 0x14, /* CR */ + WB_FPEC_BASE + 0x20, /* OPTR */ + L4_FLASH_SIZE_REG, /* FLASHSIZE */ +}; + struct stm32l4_info { char designator[10]; uint16_t sram1; /* Normal SRAM mapped at 0x20000000*/ @@ -303,6 +314,15 @@ static struct stm32l4_info const L4info[] = { .flags = 2, .flash_regs_map = stm32wl_flash_regs_map, }, + { + .idcode = ID_STM32WBXX, + .family = FAM_STM32WBxx, + .designator = "STM32WBxx", + .sram1 = 192, + .sram2 = 64, + .flags = 2, + .flash_regs_map = stm32wb_flash_regs_map, + }, { /* Terminator */ .idcode = 0, @@ -418,7 +438,9 @@ static bool stm32l4_attach(target *t) /* Add the flash to memory map. */ uint32_t options = stm32l4_flash_read32(t, FLASH_OPTR); - if (chip->family == FAM_STM32L4Rx) { + if (chip->family == FAM_STM32WBxx) { + stm32l4_add_flash(t, 0x08000000, size << 10, 0x1000, -1); + } else if (chip->family == FAM_STM32L4Rx) { /* rm0432 Rev. 2 does not mention 1 MB devices or explain DB1M.*/ if (options & OR_DBANK) { stm32l4_add_flash(t, 0x08000000, 0x00100000, 0x1000, 0x08100000); @@ -690,6 +712,10 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[]) tc_printf(t, "STM32WLxx options not implemented!\n"); return false; } + if (t->idcode == ID_STM32WBXX) { + tc_printf(t, "STM32WBxx options not implemented!\n"); + return false; + } static const uint32_t g4_values[11] = { /* SEC_SIZE1 occupies 9 bits on G49/G4A (cat 4), * 8 bits on cat 3 and 7 bits on cat 2. From f28f05952f37724d8c3e7fb3f30757de85ec55b3 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 28 Sep 2021 22:20:06 +0200 Subject: [PATCH 03/31] stlink: Add another STLINK-V3 ID. --- src/platforms/hosted/bmp_libusb.c | 1 + src/platforms/hosted/platform.h | 1 + src/platforms/hosted/stlinkv2.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index fdcb2efc..1dbb807a 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -232,6 +232,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) if ((desc.idProduct == PRODUCT_ID_STLINKV2) || (desc.idProduct == PRODUCT_ID_STLINKV21) || (desc.idProduct == PRODUCT_ID_STLINKV21_MSD) || + (desc.idProduct == PRODUCT_ID_STLINKV3_NO_MSD) || (desc.idProduct == PRODUCT_ID_STLINKV3_BL) || (desc.idProduct == PRODUCT_ID_STLINKV3) || (desc.idProduct == PRODUCT_ID_STLINKV3E)) { diff --git a/src/platforms/hosted/platform.h b/src/platforms/hosted/platform.h index 339fec85..80a29e2b 100644 --- a/src/platforms/hosted/platform.h +++ b/src/platforms/hosted/platform.h @@ -23,6 +23,7 @@ void platform_buffer_flush(void); #define PRODUCT_ID_STLINKV2 0x3748 #define PRODUCT_ID_STLINKV21 0x374b #define PRODUCT_ID_STLINKV21_MSD 0x3752 +#define PRODUCT_ID_STLINKV3_NO_MSD 0x3754 #define PRODUCT_ID_STLINKV3_BL 0x374d #define PRODUCT_ID_STLINKV3 0x374f #define PRODUCT_ID_STLINKV3E 0x374e diff --git a/src/platforms/hosted/stlinkv2.c b/src/platforms/hosted/stlinkv2.c index 5dd99dd4..fd6f9335 100644 --- a/src/platforms/hosted/stlinkv2.c +++ b/src/platforms/hosted/stlinkv2.c @@ -553,6 +553,7 @@ int stlink_init(bmp_info_t *info) case PRODUCT_ID_STLINKV3_BL: case PRODUCT_ID_STLINKV3: case PRODUCT_ID_STLINKV3E: + case PRODUCT_ID_STLINKV3_NO_MSD: Stlink.ver_hw = 30; info->usb_link->ep_tx = 1; Stlink.ep_tx = 1; From f4117aa1b447fdae9673b9368b52dd34cb1acf87 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 2 Oct 2021 20:20:17 +0200 Subject: [PATCH 04/31] cdcacm: Use the USB strings. --- src/platforms/common/cdcacm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index e28a5704..fc85b16d 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -174,7 +174,7 @@ static const struct usb_iface_assoc_descriptor gdb_assoc = { .bFunctionClass = USB_CLASS_CDC, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, .bFunctionProtocol = USB_CDC_PROTOCOL_NONE, - .iFunction = 0, + .iFunction = 4, }; /* Serial ACM interface */ @@ -277,7 +277,7 @@ static const struct usb_iface_assoc_descriptor uart_assoc = { .bFunctionClass = USB_CLASS_CDC, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, .bFunctionProtocol = USB_CDC_PROTOCOL_NONE, - .iFunction = 0, + .iFunction = 5, }; const struct usb_dfu_descriptor dfu_function = { @@ -396,7 +396,6 @@ static const struct usb_config_descriptor config = { static char serial_no[DFU_SERIAL_LENGTH]; #define BOARD_IDENT "Black Magic Probe " PLATFORM_IDENT FIRMWARE_VERSION -#define DFU_IDENT "Black Magic Firmware Upgrade " PLATFORM_IDENT FIRMWARE_VERSION static const char *usb_strings[] = { "Black Sphere Technologies", @@ -404,7 +403,7 @@ static const char *usb_strings[] = { serial_no, "Black Magic GDB Server", "Black Magic UART Port", - DFU_IDENT, + "Black Magic DFU", #if defined(PLATFORM_HAS_TRACESWO) "Black Magic Trace Capture", #endif From 99a5fdb6f87a889c8808b96b1f1c620dc438df1a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 3 Oct 2021 17:21:29 +0200 Subject: [PATCH 05/31] bmp_remote: Better error propagation. Negative values from platform_buffer_read are errors too! --- src/platforms/hosted/bmp_remote.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/platforms/hosted/bmp_remote.c b/src/platforms/hosted/bmp_remote.c index 1ca68621..8a586e2a 100644 --- a/src/platforms/hosted/bmp_remote.c +++ b/src/platforms/hosted/bmp_remote.c @@ -42,7 +42,7 @@ int remote_init(void) platform_buffer_write((uint8_t *)construct, c); c = platform_buffer_read((uint8_t *)construct, REMOTE_MAX_MSG_SIZE); - if ((!c) || (construct[0] == REMOTE_RESP_ERR)) { + if ((c < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("Remote Start failed, error %s\n", c ? (char *)&(construct[1]) : "unknown"); return -1; @@ -62,7 +62,7 @@ bool remote_target_get_power(void) s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN(" platform_target_get_power failed, error %s\n", s ? (char *)&(construct[1]) : "unknown"); exit (-1); @@ -82,7 +82,7 @@ bool remote_target_set_power(bool power) s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("platform_target_set_power failed, error %s\n", s ? (char *)&(construct[1]) : "unknown"); return false; @@ -101,7 +101,7 @@ void remote_srst_set_val(bool assert) s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("platform_srst_set_val failed, error %s\n", s ? (char *)&(construct[1]) : "unknown"); exit(-1); @@ -119,7 +119,7 @@ bool remote_srst_get_val(void) s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("platform_srst_set_val failed, error %s\n", s ? (char *)&(construct[1]) : "unknown"); exit(-1); @@ -137,7 +137,7 @@ void remote_max_frequency_set(uint32_t freq) s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("Update Firmware to allow to set max SWJ frequency\n"); } } @@ -153,7 +153,7 @@ uint32_t remote_max_frequency_get(void) s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) return FREQ_FIXED; uint32_t freq[1]; @@ -172,7 +172,7 @@ const char *remote_target_voltage(void) s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("platform_target_voltage failed, error %s\n", s ? (char *)&(construct[1]) : "unknown"); exit(- 1); @@ -188,7 +188,7 @@ static uint32_t remote_adiv5_dp_read(ADIv5_DP_t *dp, uint16_t 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)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("%s error %d\n", __func__, s); } uint32_t dest[1]; @@ -206,7 +206,7 @@ static uint32_t remote_adiv5_low_access( 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)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("%s error %d\n", __func__, s); } uint32_t dest[1]; @@ -221,7 +221,7 @@ static uint32_t remote_adiv5_ap_read(ADIv5_AP_t *ap, uint16_t 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)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("%s error %d\n", __func__, s); } uint32_t dest[1]; @@ -236,7 +236,7 @@ static void remote_adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t 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)) { + if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("%s error %d\n", __func__, s); } return; @@ -372,7 +372,7 @@ 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 < 1) || (construct[0] == REMOTE_RESP_ERR) || ((construct[1] - '0') < REMOTE_HL_VERSION)) { DEBUG_WARN( "Please update BMP firmware for substantial speed increase!\n"); From e7e1bfdb53c09e2471875194a952918d8953e78d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 26 Oct 2021 12:23:10 +0200 Subject: [PATCH 06/31] mpsse: Fix using 60 MHz clock on fast devices. --- src/platforms/hosted/ftdi_bmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/hosted/ftdi_bmp.c b/src/platforms/hosted/ftdi_bmp.c index 8244deb0..fb67d008 100644 --- a/src/platforms/hosted/ftdi_bmp.c +++ b/src/platforms/hosted/ftdi_bmp.c @@ -379,7 +379,7 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) case TYPE_2232H: case TYPE_4232H: case TYPE_232H: - ftdi_init[index++] = EN_DIV_5; + ftdi_init[index++] = DIS_DIV_5; break; case TYPE_2232C: break; From 5dafc0828c2adc1f29f737a2468d7f17cbb6ff86 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 23 Oct 2021 20:02:19 +0200 Subject: [PATCH 07/31] SWD: Remove excessive line resets. --- src/target/adiv5_swdp.c | 6 +++--- src/target/cortexm.c | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 78d91eb6..2af37c00 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -195,9 +195,8 @@ uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr) uint32_t firmware_swdp_error(ADIv5_DP_t *dp) { - uint32_t err, clr = 0; - - if ((dp->idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { + if ((dp->fault && (dp->idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) && + dp->dp_low_write) { /* On protocoll error target gets deselected. * With DP Change, another target needs selection. * => Reselect with right target! */ @@ -206,6 +205,7 @@ uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr) uint32_t dummy; dp->dp_low_read(dp, ADIV5_DP_IDCODE, &dummy); } + uint32_t err, clr = 0; err = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT) & (ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP | ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR); diff --git a/src/target/cortexm.c b/src/target/cortexm.c index d0877b7e..5ce3a3c6 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -478,6 +478,9 @@ bool cortexm_probe(ADIv5_AP_t *ap) bool cortexm_attach(target *t) { + ADIv5_AP_t *ap = cortexm_ap(t); + ap->dp->fault = 1; /* Force switch to this multi-drop device*/ + target_check_error(t); struct cortexm_priv *priv = t->priv; unsigned i; uint32_t r; From c4b6b42dcfab33a74e358508aa42e6091189d1e7 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 25 Oct 2021 13:19:16 +0200 Subject: [PATCH 08/31] stlinkv2: Read targetid on DPv2 devices. --- src/platforms/hosted/stlinkv2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/platforms/hosted/stlinkv2.c b/src/platforms/hosted/stlinkv2.c index fd6f9335..4f805593 100644 --- a/src/platforms/hosted/stlinkv2.c +++ b/src/platforms/hosted/stlinkv2.c @@ -1049,7 +1049,7 @@ int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp) uint8_t data[2]; stlink_send_recv_retry(cmd, 16, data, 2); if (stlink_usb_error_check(data, true)) - return -1; + exit( -1); dp->idcode = stlink_read_coreid(); dp->dp_read = stlink_dp_read; dp->error = stlink_dp_error; @@ -1057,6 +1057,12 @@ int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp) dp->abort = stlink_dp_abort; stlink_dp_error(dp); + if ((dp->idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { + adiv5_dp_write(dp, ADIV5_DP_SELECT, 2); + dp->targetid = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); + adiv5_dp_write(dp, ADIV5_DP_SELECT, 0); + DEBUG_INFO("TARGETID 0x%08" PRIx32 "\n", dp->targetid); + } return 0; } From 8845a22226e3ad0e378021c5ece3441f9d399f23 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 26 Oct 2021 13:01:49 +0200 Subject: [PATCH 09/31] stm32l4: Use targetid when available. Fixes STM32U5 from crashing. --- src/target/stm32l4.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index 9ff64532..cdd9fdf2 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -507,22 +507,31 @@ static void stm32l4_detach(target *t) bool stm32l4_probe(target *t) { - uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS; ADIv5_AP_t *ap = cortexm_ap(t); - if (ap->dp->idcode == 0x0Be12477) { - idcode_reg = STM32L5_DBGMCU_IDCODE_PHYS; - if ((stm32l4_flash_read32(t, FLASH_OPTR)) & L5_FLASH_OPTR_TZEN) { - DEBUG_WARN("STM32L5 Trust Zone enabled\n"); - } + uint32_t idcode; + if (ap->dp->targetid > 1) { /* STM32L552 has in valid TARGETID 1 */ + idcode = (ap->dp->targetid >> 16) & 0xfff; + } else { + uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS; + if (ap->dp->idcode == 0x0Be12477) + idcode_reg = STM32L5_DBGMCU_IDCODE_PHYS; + idcode = target_mem_read32(t, idcode_reg) & 0xfff; + DEBUG_INFO("Idcode %08" PRIx32 "\n", idcode); } - uint32_t idcode = target_mem_read32(t, idcode_reg) & 0xfff; - DEBUG_INFO("Read %" PRIx32 ": %" PRIx32 "\n", idcode_reg, idcode); struct stm32l4_info const *chip = stm32l4_get_chip_info(idcode); if( !chip->idcode ) /* Not found */ return false; + switch (idcode) { + case ID_STM32L55: + if ((stm32l4_flash_read32(t, FLASH_OPTR)) & L5_FLASH_OPTR_TZEN) { + DEBUG_WARN("STM32L5 Trust Zone enabled\n"); + t->core = "M33(TZ)"; + break; + } + } t->driver = chip->designator; t->attach = stm32l4_attach; t->detach = stm32l4_detach; From 80064c18a96a940e3fbe71319b00b4fbfacc8610 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 30 Oct 2021 13:56:11 +0200 Subject: [PATCH 10/31] bmp_libusb: Fix CMSIS-DAP related memory leak. --- src/platforms/hosted/bmp_libusb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 1dbb807a..5dbfcb7d 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -68,6 +68,7 @@ static bmp_type_t find_cmsis_dap_interface(libusb_device *dev,bmp_info_t *info) if (res != LIBUSB_SUCCESS) { DEBUG_INFO("INFO: libusb_open() failed: %s\n", libusb_strerror(res)); + libusb_free_config_descriptor(conf); return type; } @@ -110,10 +111,10 @@ static bmp_type_t find_cmsis_dap_interface(libusb_device *dev,bmp_info_t *info) } /* V2 is preferred, return early. */ - return type; + break; } } - + libusb_free_config_descriptor(conf); return type; } From 7b1eb6e6e3b44cb69d0b722e4af7889097bbb009 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 30 Oct 2021 17:23:31 +0200 Subject: [PATCH 11/31] bmp_libusb: reset type on every device. --- src/platforms/hosted/bmp_libusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 5dbfcb7d..b14dce09 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -155,7 +155,6 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) char *active_cable = NULL; bool ftdi_unknown = false; rescan: - type = BMP_TYPE_NONE; found_debuggers = 0; serial[0] = 0; manufacturer[0] = 0; @@ -164,6 +163,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) active_cable = NULL; ftdi_unknown = false; for (int i = 0; devs[i]; i++) { + type = BMP_TYPE_NONE; libusb_device *dev = devs[i]; int res = libusb_get_device_descriptor(dev, &desc); if (res < 0) { From 397fbd5749f9a1999b5ad0fb35b20e54a50a5341 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 21 Oct 2021 17:51:28 +0200 Subject: [PATCH 12/31] cmsis: Only cmsis internal use must differentiate between HID and Bulk access Missing DAP_SWD_SEQUENCE may eventually need a distinction visible from outside later. --- src/platforms/hosted/bmp_libusb.c | 10 +++------ src/platforms/hosted/cmsis_dap.c | 23 +++++++++++++------- src/platforms/hosted/platform.c | 36 +++++++++++-------------------- src/platforms/hosted/platform.h | 3 +-- 4 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index b14dce09..d2949320 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -91,13 +91,9 @@ static bmp_type_t find_cmsis_dap_interface(libusb_device *dev,bmp_info_t *info) if (!strstr(interface_string, "CMSIS")) { continue; } + type = BMP_TYPE_CMSIS_DAP; - if (interface->bInterfaceClass == 0x03) { - type = BMP_TYPE_CMSIS_DAP_V1; - - } else if (interface->bInterfaceClass == 0xff && interface->bNumEndpoints == 2) { - type = BMP_TYPE_CMSIS_DAP_V2; - + if (interface->bInterfaceClass == 0xff && interface->bNumEndpoints == 2) { info->interface_num = interface->bInterfaceNumber; for (int j = 0; j < interface->bNumEndpoints; j++) { @@ -228,7 +224,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) ((type = find_cmsis_dap_interface(dev, info)) != BMP_TYPE_NONE)) { /* find_cmsis_dap_interface has set valid type*/ } else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) { - type = BMP_TYPE_CMSIS_DAP_V1; + type = BMP_TYPE_CMSIS_DAP; } else if (desc.idVendor == VENDOR_ID_STLINK) { if ((desc.idProduct == PRODUCT_ID_STLINKV2) || (desc.idProduct == PRODUCT_ID_STLINKV21) || diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 002c44a4..c06ef9e2 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -45,8 +45,13 @@ uint8_t dap_caps; uint8_t mode; +typedef enum cmsis_type_s { + CMSIS_TYPE_NONE = 0, + CMSIS_TYPE_HID, + CMSIS_TYPE_BULK +} cmsis_type_t; /*- Variables ---------------------------------------------------------------*/ -static bmp_type_t type; +static cmsis_type_t type; static libusb_device_handle *usb_handle = NULL; static uint8_t in_ep; static uint8_t out_ep; @@ -58,10 +63,11 @@ static bool has_swd_sequence = false; /* LPC845 Breakout Board Rev. 0 report invalid response with > 65 bytes */ int dap_init(bmp_info_t *info) { - type = info->bmp_type; + type = (info->in_ep && info->out_ep) ? CMSIS_TYPE_BULK : CMSIS_TYPE_HID; int size; - if (type == BMP_TYPE_CMSIS_DAP_V1) { + if (type == CMSIS_TYPE_HID) { + DEBUG_INFO("Using hid transfer\n"); if (hid_init()) return -1; size = strlen(info->serial); @@ -79,7 +85,8 @@ int dap_init(bmp_info_t *info) handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL); if (!handle) return -1; - } else if (type == BMP_TYPE_CMSIS_DAP_V2) { + } else if (type == CMSIS_TYPE_BULK) { + DEBUG_INFO("Using bulk transfer\n"); usb_handle = libusb_open_device_with_vid_pid(info->libusb_ctx, info->vid, info->pid); if (!usb_handle) { DEBUG_WARN("WARN: libusb_open_device_with_vid_pid() failed\n"); @@ -175,12 +182,12 @@ static uint32_t dap_dp_read_reg(ADIv5_DP_t *dp, uint16_t addr) void dap_exit_function(void) { - if (type == BMP_TYPE_CMSIS_DAP_V1) { + if (type == CMSIS_TYPE_HID) { if (handle) { dap_disconnect(); hid_close(handle); } - } else if (type == BMP_TYPE_CMSIS_DAP_V2) { + } else if (type == CMSIS_TYPE_BULK) { if (usb_handle) { dap_disconnect(); libusb_close(usb_handle); @@ -208,7 +215,7 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) for(int i = 0; (i < 32) && (i < rsize + 1); i++) DEBUG_WIRE("%02x.", buffer[i]); DEBUG_WIRE("\n"); - if (type == BMP_TYPE_CMSIS_DAP_V1) { + if (type == CMSIS_TYPE_HID) { res = hid_write(handle, buffer, rsize + 1); if (res < 0) { DEBUG_WARN( "Error: %ls\n", hid_error(handle)); @@ -219,7 +226,7 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle)); exit(-1); } - } else if (type == BMP_TYPE_CMSIS_DAP_V2) { + } else if (type == CMSIS_TYPE_BULK) { int transferred = 0; res = libusb_bulk_transfer(usb_handle, out_ep, buffer + 1, rsize, &transferred, 0); diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index df657d5f..4faed409 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -52,8 +52,7 @@ static void exit_function(void) { libusb_exit_function(&info); switch (info.bmp_type) { - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: dap_exit_function(); break; default: @@ -93,8 +92,7 @@ void platform_init(int argc, char **argv) if (stlink_init( &info)) exit(-1); break; - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: if (dap_init( &info)) exit(-1); break; @@ -126,8 +124,7 @@ int platform_adiv5_swdp_scan(uint32_t targetid) switch (info.bmp_type) { case BMP_TYPE_BMP: case BMP_TYPE_LIBFTDI: - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: return adiv5_swdp_scan(targetid); break; case BMP_TYPE_STLINKV2: @@ -156,8 +153,7 @@ int swdptap_init(ADIv5_DP_t *dp) switch (info.bmp_type) { case BMP_TYPE_BMP: return remote_swdptap_init(dp); - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: return dap_swdptap_init(dp); case BMP_TYPE_STLINKV2: case BMP_TYPE_JLINK: @@ -184,8 +180,7 @@ int platform_jtag_scan(const uint8_t *lrlens) case BMP_TYPE_BMP: case BMP_TYPE_LIBFTDI: case BMP_TYPE_JLINK: - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: return jtag_scan(lrlens); case BMP_TYPE_STLINKV2: return jtag_scan_stlinkv2(&info, lrlens); @@ -206,8 +201,7 @@ int platform_jtagtap_init(void) return libftdi_jtagtap_init(&jtag_proc); case BMP_TYPE_JLINK: return jlink_jtagtap_init(&info, &jtag_proc); - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: return cmsis_dap_jtagtap_init(&jtag_proc); default: return -1; @@ -226,8 +220,7 @@ void platform_adiv5_dp_defaults(ADIv5_DP_t *dp) return remote_adiv5_dp_defaults(dp); case BMP_TYPE_STLINKV2: return stlink_adiv5_dp_defaults(dp); - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: return dap_adiv5_dp_defaults(dp); default: break; @@ -243,8 +236,7 @@ int platform_jtag_dp_init(ADIv5_DP_t *dp) return 0; case BMP_TYPE_STLINKV2: return stlink_jtag_dp_init(dp); - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: return dap_jtag_dp_init(dp); default: return 0; @@ -263,10 +255,8 @@ char *platform_ident(void) return "STLINKV2"; case BMP_TYPE_LIBFTDI: return "LIBFTDI"; - case BMP_TYPE_CMSIS_DAP_V1: - return "CMSIS_DAP_V1"; - case BMP_TYPE_CMSIS_DAP_V2: - return "CMSIS_DAP_V2"; + case BMP_TYPE_CMSIS_DAP: + return "CMSIS_DAP"; case BMP_TYPE_JLINK: return "JLINK"; } @@ -331,8 +321,7 @@ void platform_max_frequency_set(uint32_t freq) case BMP_TYPE_BMP: remote_max_frequency_set(freq); break; - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: dap_swj_clock(freq); break; case BMP_TYPE_LIBFTDI: @@ -363,8 +352,7 @@ uint32_t platform_max_frequency_get(void) switch (info.bmp_type) { case BMP_TYPE_BMP: return remote_max_frequency_get(); - case BMP_TYPE_CMSIS_DAP_V1: - case BMP_TYPE_CMSIS_DAP_V2: + case BMP_TYPE_CMSIS_DAP: return dap_swj_clock(0); break; case BMP_TYPE_LIBFTDI: diff --git a/src/platforms/hosted/platform.h b/src/platforms/hosted/platform.h index 80a29e2b..3ac453de 100644 --- a/src/platforms/hosted/platform.h +++ b/src/platforms/hosted/platform.h @@ -35,8 +35,7 @@ typedef enum bmp_type_s { BMP_TYPE_BMP, BMP_TYPE_STLINKV2, BMP_TYPE_LIBFTDI, - BMP_TYPE_CMSIS_DAP_V1, - BMP_TYPE_CMSIS_DAP_V2, + BMP_TYPE_CMSIS_DAP, BMP_TYPE_JLINK } bmp_type_t; From 485105221e8177d90b641f9a3304ad415791fb9e Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 8 Oct 2021 12:50:31 +0200 Subject: [PATCH 13/31] dap: Always work on a copy of the buffer when calling dbg_dap_cmd() in a loop A better solution would use seperate buffers for dbg_dap_cmd. But as WAIT is already handled in DAP, cahnces are low that loop re-entry is needed. --- src/platforms/hosted/dap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 35bce96b..b2827bf0 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -326,11 +326,10 @@ static uint32_t wait_word(uint8_t *buf, int size, int len, uint8_t *dp_fault) uint8_t cmd_copy[len]; memcpy(cmd_copy, buf, len); do { + memcpy(buf, cmd_copy, len); dbg_dap_cmd(buf, size, len); if (buf[1] < DAP_TRANSFER_WAIT) break; - if (buf[1] == DAP_TRANSFER_WAIT) - memcpy(buf, cmd_copy, len); } while (buf[1] == DAP_TRANSFER_WAIT); if (buf[1] > DAP_TRANSFER_WAIT) { @@ -378,7 +377,10 @@ void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data) buf[5] = (data >> 8) & 0xff; buf[6] = (data >> 16) & 0xff; buf[7] = (data >> 24) & 0xff; + uint8_t cmd_copy[8]; + memcpy(cmd_copy, buf, 8); do { + memcpy(buf, cmd_copy, 8); dbg_dap_cmd(buf, sizeof(buf), 8); if (buf[1] < DAP_TRANSFER_WAIT) break; From b7e7aa3f9ab6fbf345e1400f05baf5481188f26a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 8 Oct 2021 12:59:18 +0200 Subject: [PATCH 14/31] adiv5: Either use only LL functions in cortexm_initial_halt or no LL at all. Platform implementation may disturb ADIV5_AP_DRW and so low_read DHCSR may give values other from registers --- 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 d337d1fa..429d6125 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -337,7 +337,7 @@ static uint32_t cortexm_initial_halt(ADIv5_AP_t *ap) while (!platform_timeout_is_expired(&to)) { uint32_t dhcsr ; if (use_low_access) { - adiv5_dp_write(ap->dp, ADIV5_DP_CTRLSTAT, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_DP_CTRLSTAT, ctrlstat | (0xfff * ADIV5_DP_CTRLSTAT_TRNCNT)); adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DRW, dhcsr_ctl); From c13778139f857f6896b7a5ba64d207433aa523f4 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 8 Oct 2021 18:40:15 +0200 Subject: [PATCH 15/31] adiv5/hosted: Export the BMP_TYPE in DP. --- src/platforms/hosted/cmsis_dap.c | 2 ++ src/platforms/hosted/platform.c | 1 + src/target/adiv5.h | 1 + 3 files changed, 4 insertions(+) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index c06ef9e2..77c77992 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -127,6 +127,8 @@ int dap_init(bmp_info_t *info) DEBUG_INFO(", SWO_MANCHESTER"); if (dap_caps & 0x10) DEBUG_INFO(", Atomic Cmds"); + if (has_swd_sequence) + DEBUG_INFO(", DAP_SWD_Sequence"); DEBUG_INFO("\n"); return 0; } diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 4faed409..abb6557c 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -211,6 +211,7 @@ int platform_jtagtap_init(void) void platform_adiv5_dp_defaults(ADIv5_DP_t *dp) { + dp->dp_bmp_type = info.bmp_type; switch (info.bmp_type) { case BMP_TYPE_BMP: if (cl_opts.opt_no_hl) { diff --git a/src/target/adiv5.h b/src/target/adiv5.h index c8b77cc1..b995af8e 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -182,6 +182,7 @@ typedef struct ADIv5_DP_s { void (*abort)(struct ADIv5_DP_s *dp, uint32_t abort); #if PC_HOSTED == 1 + bmp_type_t dp_bmp_type; bool (*ap_setup)(int i); void (*ap_cleanup)(int i); void (*ap_regs_read)(ADIv5_AP_t *ap, void *data); From 39fbffd3d2aac33fdb74b84c2e2596012949cf46 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 9 Oct 2021 13:10:23 +0200 Subject: [PATCH 16/31] stlinkv2: Fix low access to AP registers. --- src/platforms/hosted/stlinkv2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/stlinkv2.c b/src/platforms/hosted/stlinkv2.c index 4f805593..42e81dd9 100644 --- a/src/platforms/hosted/stlinkv2.c +++ b/src/platforms/hosted/stlinkv2.c @@ -764,9 +764,10 @@ uint32_t stlink_dp_low_access(ADIv5_DP_t *dp, uint8_t RnW, int res; if (RnW) { res = stlink_read_dp_register( - STLINK_DEBUG_PORT_ACCESS, addr, &response); + (addr < 0x100) ? STLINK_DEBUG_PORT_ACCESS : 0, addr, &response); } else { - res = stlink_write_dp_register(STLINK_DEBUG_PORT_ACCESS, addr, value); + res = stlink_write_dp_register( + (addr < 0x100) ? STLINK_DEBUG_PORT_ACCESS : 0, addr, value); } if (res == STLINK_ERROR_WAIT) raise_exception(EXCEPTION_TIMEOUT, "DP ACK timeout"); From 761e0230d42dbc25be0a2b744d34770dd839a880 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 9 Oct 2021 22:59:32 +0200 Subject: [PATCH 17/31] cmsis-dap: Print messages when transfers fail. Expect signal integrity errors when using jumper cables. Often probes switch the SWJ GPIO with highest speed, resulting in possible reflections. Additional ground wires may help. If there is isolation between probe and targets, additional ground wires are a must or ground shift will wrack the transfer! --- src/platforms/hosted/cmsis_dap.c | 4 +++- src/platforms/hosted/dap.c | 20 ++++++++++++++------ src/target/adiv5_swdp.c | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 77c77992..d01c2b8b 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -83,8 +83,10 @@ int dap_init(bmp_info_t *info) report_size = 64 + 1; } handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL); - if (!handle) + if (!handle) { + DEBUG_WARN("hid_open failed\n"); return -1; + } } else if (type == CMSIS_TYPE_BULK) { DEBUG_INFO("Using bulk transfer\n"); usb_handle = libusb_open_device_with_vid_pid(info->libusb_ctx, info->vid, info->pid); diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index b2827bf0..7fbe72a3 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -333,12 +333,14 @@ static uint32_t wait_word(uint8_t *buf, int size, int len, uint8_t *dp_fault) } while (buf[1] == DAP_TRANSFER_WAIT); if (buf[1] > DAP_TRANSFER_WAIT) { -// DEBUG_WARN("dap_read_reg fault\n"); + DEBUG_WARN("dap wait_word reg %x fault %x\n", + cmd_copy[3] & 0x7c, buf[1]); *dp_fault = 1; - } - if (buf[1] == DAP_TRANSFER_ERROR) { - DEBUG_WARN("dap_read_reg, protocoll error\n"); - dap_line_reset(); + if (buf[1] == DAP_TRANSFER_ERROR) { + DEBUG_WARN("dap_read_reg, protocoll error\n"); + dap_line_reset(); + } + return 0; } uint32_t res = ((uint32_t)buf[5] << 24) | ((uint32_t)buf[4] << 16) | @@ -568,7 +570,7 @@ void dap_ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align) uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr) { - DEBUG_PROBE("dap_ap_read_start\n"); + DEBUG_PROBE("dap_ap_read_start addr %x\n", addr); uint8_t buf[63], *p = buf; buf[0] = ID_DAP_TRANSFER; uint8_t dap_index = 0; @@ -584,6 +586,9 @@ uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr) *p++ = (addr & 0x0c) | DAP_TRANSFER_RnW | ((addr & 0x100) ? DAP_TRANSFER_APnDP : 0); uint32_t res = wait_word(buf, 63, p - buf, &ap->dp->fault); + if ((buf[0] != 2) || (buf[1] != 1)) { + DEBUG_WARN("dap_ap_read error %x\n", buf[1]); + } return res; } @@ -607,6 +612,9 @@ void dap_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value) *p++ = (value >> 16) & 0xff; *p++ = (value >> 24) & 0xff; dbg_dap_cmd(buf, sizeof(buf), p - buf); + if ((buf[0] != 2) || (buf[1] != 1)) { + DEBUG_WARN("dap_ap_write error %x\n", buf[1]); + } } void dap_read_single(ADIv5_AP_t *ap, void *dest, uint32_t src, enum align align) diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 2af37c00..2e584316 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -124,7 +124,7 @@ int adiv5_swdp_scan(uint32_t targetid) idcode = initial_dp->low_access(initial_dp, ADIV5_LOW_READ, ADIV5_DP_IDCODE, 0); } - if (e2.type) { + if (e2.type || initial_dp->fault) { DEBUG_WARN("No usable DP found\n"); return 0; } From d144f9d54b66d07c56873d6f3507250a08a79184 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 9 Oct 2021 13:12:10 +0200 Subject: [PATCH 18/31] adiv5: CMSIS DAP transactions are slow but work in principle Slowness results in strange STM32F767 DHCSR implementation to nearly never halt in the given 2 second period when F767 is sleeping most of the time. --- src/target/adiv5.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 429d6125..a257175a 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -323,12 +323,7 @@ static uint32_t cortexm_initial_halt(ADIv5_AP_t *ap) CORTEXM_DHCSR_C_HALT; uint32_t dhcsr_valid = CORTEXM_DHCSR_S_HALT | CORTEXM_DHCSR_C_DEBUGEN; bool reset_seen = false; - bool is_mindp = (ap->dp->idcode & ADIV5_MINDP); -#if PC_HOSTED == 1 - bool use_low_access = (!(ap->dp->ap_setup) && !is_mindp); -#else - bool use_low_access = (!is_mindp); -#endif + bool use_low_access = (!(ap->dp->idcode & ADIV5_MINDP)); if (use_low_access) { /* ap_mem_access_setup() sets ADIV5_AP_CSW_ADDRINC_SINGLE -> unusable!*/ adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD); From b343ebe06f303ebe5d46e4a05aaceafcf0a04b3d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 14 Oct 2021 11:45:36 +0200 Subject: [PATCH 19/31] cmsis-dap/linux: Link against libhidapi-hidraw libhidapi-libusb detaches a kernel module but does not reattach again. This may wrack interaction with other programs using hidapi. --- src/platforms/hosted/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index ad888638..f3e3248b 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -18,7 +18,7 @@ CFLAGS += -DHOSTED_BMP_ONLY=$(HOSTED_BMP_ONLY) ifneq (, $(findstring linux, $(SYS))) SRC += serial_unix.c -HIDAPILIB = hidapi-libusb +HIDAPILIB = hidapi-hidraw ifeq ($(ASAN), 1) CFLAGS += -fsanitize=address -Wno-format-truncation LDFLAGS += -lasan From 166eb3ee3eb736ece3e874738e8eb564e3f08cbb Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 11 Oct 2021 20:57:49 +0200 Subject: [PATCH 20/31] cmsis_dap: Always transfer 65 bytes with hid_read|write() CMSIS-DAP Dragonprobe works on some devices. E.g. it does not work on NUCLEO-F103 --- src/platforms/hosted/cmsis_dap.c | 7 +++++-- src/platforms/hosted/dap.c | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index d01c2b8b..d9fff760 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -220,15 +220,18 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) DEBUG_WIRE("%02x.", buffer[i]); DEBUG_WIRE("\n"); if (type == CMSIS_TYPE_HID) { - res = hid_write(handle, buffer, rsize + 1); + res = hid_write(handle, buffer, 65); if (res < 0) { DEBUG_WARN( "Error: %ls\n", hid_error(handle)); exit(-1); } - res = hid_read(handle, buffer, report_size + 1); + res = hid_read_timeout(handle, buffer, 65, 1000); if (res < 0) { DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle)); exit(-1); + } else if (res == 0) { + DEBUG_WARN( "timeout\n"); + exit(-1); } } else if (type == CMSIS_TYPE_BULK) { int transferred = 0; diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 7fbe72a3..1db94824 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -197,10 +197,10 @@ 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); + dbg_dap_cmd(buf, sizeof(buf), 65); } static uint32_t swj_clock; From d4ae308f9fd06baad7a2c54074e01ff623baaa3d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 22 Oct 2021 18:36:23 +0200 Subject: [PATCH 21/31] cmsis: implement srst_set_val() --- src/platforms/hosted/cmsis_dap.c | 5 +++++ src/platforms/hosted/cmsis_dap.h | 2 ++ src/platforms/hosted/dap.c | 7 ++----- src/platforms/hosted/dap.h | 1 + src/platforms/hosted/platform.c | 2 ++ 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index d9fff760..d3c17466 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -135,6 +135,11 @@ int dap_init(bmp_info_t *info) return 0; } +void dap_srst_set_val(bool assert) +{ + dap_reset_pin(!assert); +} + static void dap_dp_abort(ADIv5_DP_t *dp, uint32_t abort) { /* DP Write to Reg 0.*/ diff --git a/src/platforms/hosted/cmsis_dap.h b/src/platforms/hosted/cmsis_dap.h index a060d585..ed5c6c78 100644 --- a/src/platforms/hosted/cmsis_dap.h +++ b/src/platforms/hosted/cmsis_dap.h @@ -31,6 +31,7 @@ int dap_swdptap_init(ADIv5_DP_t *dp); int dap_jtag_dp_init(ADIv5_DP_t *dp); uint32_t dap_swj_clock(uint32_t clock); void dap_swd_configure(uint8_t cfg); +void dap_srst_set_val(bool assert); #else int dap_init(bmp_info_t *info) { @@ -47,6 +48,7 @@ int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc) {return -1;} int dap_swdptap_init(ADIv5_DP_t *dp) {return -1;} int dap_jtag_dp_init(ADIv5_DP_t *dp) {return -1;} void dap_swd_configure(uint8_t cfg) {}; +void dap_srst_set_val(assert) {}; # pragma GCC diagnostic pop #endif diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 1db94824..565d576a 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -200,7 +200,7 @@ void dap_disconnect(void) uint8_t buf[65]; buf[0] = ID_DAP_DISCONNECT; - dbg_dap_cmd(buf, sizeof(buf), 65); + dbg_dap_cmd(buf, sizeof(buf), 1); } static uint32_t swj_clock; @@ -277,10 +277,7 @@ void dap_reset_pin(int state) buf[1] = state ? DAP_SWJ_nRESET : 0; // Value buf[2] = DAP_SWJ_nRESET; // Select buf[3] = 0; // Wait - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - dbg_dap_cmd(buf, sizeof(buf), 7); + dbg_dap_cmd(buf, sizeof(buf), 4); } void dap_trst_reset(void) diff --git a/src/platforms/hosted/dap.h b/src/platforms/hosted/dap.h index d7e11249..5d655d85 100644 --- a/src/platforms/hosted/dap.h +++ b/src/platforms/hosted/dap.h @@ -69,6 +69,7 @@ void dap_transfer_configure(uint8_t idle, uint16_t count, uint16_t retry); void dap_swd_configure(uint8_t cfg); int dap_info(int info, uint8_t *data, int size); void dap_reset_target(void); +void dap_srst_set_val(bool assert); void dap_trst_reset(void); void dap_reset_target_hw(int state); void dap_reset_pin(int state); diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index abb6557c..a90294d4 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -292,6 +292,8 @@ void platform_srst_set_val(bool assert) return jlink_srst_set_val(&info, assert); case BMP_TYPE_LIBFTDI: return libftdi_srst_set_val(assert); + case BMP_TYPE_CMSIS_DAP: + return dap_srst_set_val(assert); default: break; } From f9d343af3edc9ec2213939f58731e48f1c2b89a4 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 22 Oct 2021 13:28:27 +0200 Subject: [PATCH 22/31] cmsis: AP reads are posted. Read from RDBUFF. --- src/platforms/hosted/dap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 565d576a..1732e9d9 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -619,7 +619,8 @@ void dap_read_single(ADIv5_AP_t *ap, void *dest, uint32_t src, enum align align) uint8_t buf[63]; uint8_t *p = mem_access_setup(ap, buf, src, align); *p++ = SWD_AP_DRW | DAP_TRANSFER_RnW; - buf[2] = 4; + *p++ = SWD_DP_R_RDBUFF | DAP_TRANSFER_RnW; + buf[2] = 5; uint32_t tmp = wait_word(buf, 63, p - buf, &ap->dp->fault); dest = extract(dest, src, tmp, align); } From 4f36c1ddf8c49c9122dcfbb9a64302f2b0300095 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 23 Oct 2021 18:07:25 +0200 Subject: [PATCH 23/31] Remove dp_low_read() and use exception protected dp_read() --- src/exception.c | 2 +- src/platforms/hosted/cmsis_dap.c | 31 ------------------------------- src/target/adiv5.h | 2 -- src/target/adiv5_swdp.c | 32 ++++++++++++-------------------- 4 files changed, 13 insertions(+), 54 deletions(-) diff --git a/src/exception.c b/src/exception.c index 04c6b214..108a8687 100644 --- a/src/exception.c +++ b/src/exception.c @@ -26,7 +26,6 @@ struct exception *innermost_exception; void raise_exception(uint32_t type, const char *msg) { struct exception *e; - DEBUG_WARN("Exception: %s\n", msg); for (e = innermost_exception; e; e = e->outer) { if (e->mask & type) { e->type = type; @@ -35,6 +34,7 @@ void raise_exception(uint32_t type, const char *msg) longjmp(e->jmpbuf, type); } } + DEBUG_WARN("Unhandled exception: %s\n", msg); abort(); } diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index d3c17466..48ebc20c 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -415,36 +415,6 @@ int dap_jtag_dp_init(ADIv5_DP_t *dp) #define SWD_SEQUENCE_IN 0x80 #define DAP_SWD_SEQUENCE 0x1d -/* DAP_SWD_SEQUENCE does not do auto turnaround*/ -static bool dap_dp_low_read(ADIv5_DP_t *dp, uint16_t addr, uint32_t *res) -{ - (void)dp; - unsigned int paket_request = make_packet_request(ADIV5_LOW_READ, addr); - uint8_t buf[32] = { - DAP_SWD_SEQUENCE, - 5, - 8, - paket_request, - 4 + SWD_SEQUENCE_IN, /* one turn-around + read 3 bit ACK */ - 32 + SWD_SEQUENCE_IN, /* read 32 bit data */ - 1 + SWD_SEQUENCE_IN, /* read parity bit */ - 1, /* one bit turn around to drive SWDIO */ - 0 - }; - dbg_dap_cmd(buf, sizeof(buf), 9); - if (buf[0]) - DEBUG_WARN("dap_dp_low_read failed\n"); - uint32_t ack = (buf[1] >> 1) & 7; - uint32_t data = (buf[2] << 0) + (buf[3] << 8) + (buf[4] << 16) - + (buf[5] << 24); - int parity = __builtin_parity(data); - bool ret = ((parity != buf[6]) || (ack != 1)); - *res = data; - DEBUG_PROBE("dap_dp_low_read ack %d, res %08" PRIx32 ", parity %s\n", ack, - data, (ret)? "ERR": "OK"); - return ret; -} - static bool dap_dp_low_write(ADIv5_DP_t *dp, uint16_t addr, const uint32_t data) { DEBUG_PROBE("dap_dp_low_write %08" PRIx32 "\n", data); @@ -485,7 +455,6 @@ int dap_swdptap_init(ADIv5_DP_t *dp) dap_reset_link(false); if (has_swd_sequence) { /* DAP_SWD_SEQUENCE does not do auto turnaround, use own!*/ - dp->dp_low_read = dap_dp_low_read; dp->dp_low_write = dap_dp_low_write; } else { dp->error = dap_dp_error; diff --git a/src/target/adiv5.h b/src/target/adiv5.h index b995af8e..63abecf4 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -173,8 +173,6 @@ typedef struct ADIv5_DP_s { /* dp_low_write returns true if no OK resonse. */ bool (*dp_low_write)(struct ADIv5_DP_s *dp, uint16_t addr, const uint32_t data); - /* dp_low_read returns true with parity error */ - bool (*dp_low_read)(struct ADIv5_DP_s *dp, uint16_t addr, uint32_t *data); uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint16_t addr); uint32_t (*error)(struct ADIv5_DP_s *dp); uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t RnW, diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 2e584316..73e019dc 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -61,14 +61,6 @@ bool firmware_dp_low_write(ADIv5_DP_t *dp, uint16_t addr, const uint32_t data) return (res != 1); } -static bool firmware_dp_low_read(ADIv5_DP_t *dp, uint16_t addr, uint32_t *res) -{ - unsigned int request = make_packet_request(ADIV5_LOW_READ, addr & 0xf); - dp->seq_out(request, 8); - dp->seq_in(3); - return dp->seq_in_parity(res, 32); -} - /* Try first the dormant to SWD procedure. * If target id given, scan DPs 0 .. 15 on that device and return. * Otherwise @@ -78,7 +70,6 @@ int adiv5_swdp_scan(uint32_t targetid) target_list_free(); ADIv5_DP_t idp = { .dp_low_write = firmware_dp_low_write, - .dp_low_read = firmware_dp_low_read, .error = firmware_swdp_error, .dp_read = firmware_swdp_read, .low_access = firmware_swdp_low_access, @@ -108,8 +99,7 @@ int adiv5_swdp_scan(uint32_t targetid) dp_line_reset(initial_dp); volatile struct exception e; TRY_CATCH (e, EXCEPTION_ALL) { - idcode = initial_dp->low_access(initial_dp, ADIV5_LOW_READ, - ADIV5_DP_IDCODE, 0); + idcode = initial_dp->dp_read(initial_dp, ADIV5_DP_IDCODE); } if (e.type || initial_dp->fault) { is_v2 = false; @@ -121,8 +111,7 @@ int adiv5_swdp_scan(uint32_t targetid) initial_dp->fault = 0; volatile struct exception e2; TRY_CATCH (e2, EXCEPTION_ALL) { - idcode = initial_dp->low_access(initial_dp, ADIV5_LOW_READ, - ADIV5_DP_IDCODE, 0); + idcode = initial_dp->dp_read(initial_dp, ADIV5_DP_IDCODE); } if (e2.type || initial_dp->fault) { DEBUG_WARN("No usable DP found\n"); @@ -153,16 +142,19 @@ int adiv5_swdp_scan(uint32_t targetid) } else { target_id = targetid; } - int nr_dps = (is_v2) ? 16: 1; - uint32_t dp_targetid; - for (int i = 0; i < nr_dps; i++) { + volatile int nr_dps = (is_v2) ? 16: 1; + volatile uint32_t dp_targetid; + for (volatile int i = 0; i < nr_dps; i++) { if (is_v2) { dp_line_reset(initial_dp); dp_targetid = (i << 28) | (target_id & 0x0fffffff); initial_dp->dp_low_write(initial_dp, ADIV5_DP_TARGETSEL, dp_targetid); - if (initial_dp->dp_low_read(initial_dp, ADIV5_DP_IDCODE, - &idcode)) { + volatile struct exception e; + TRY_CATCH (e, EXCEPTION_ALL) { + idcode = initial_dp->dp_read(initial_dp, ADIV5_DP_IDCODE); + } + if (e.type || initial_dp->fault) { continue; } } else { @@ -202,8 +194,8 @@ uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr) * => Reselect with right target! */ dp_line_reset(dp); dp->dp_low_write(dp, ADIV5_DP_TARGETSEL, dp->targetid); - uint32_t dummy; - dp->dp_low_read(dp, ADIV5_DP_IDCODE, &dummy); + dp->dp_read(dp, ADIV5_DP_IDCODE); + /* Exception here is unexpected, so do not catch */ } uint32_t err, clr = 0; err = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT) & From a1d4649795bd02b2a4d3757bea1ba3dcfb05ad21 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 23 Oct 2021 21:08:26 +0200 Subject: [PATCH 24/31] SWD: Use dp_low_write to allow multidrop scan. --- src/platforms/hosted/cmsis_dap.c | 3 +-- src/platforms/hosted/dap.c | 6 +----- src/target/adiv5_swdp.c | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 48ebc20c..1a428525 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -457,10 +457,9 @@ int dap_swdptap_init(ADIv5_DP_t *dp) /* DAP_SWD_SEQUENCE does not do auto turnaround, use own!*/ dp->dp_low_write = dap_dp_low_write; } else { - dp->error = dap_dp_error; + dp->dp_low_write = NULL; } dp->seq_out = dap_swdptap_seq_out; - dp->seq_out_parity = dap_swdptap_seq_out_parity; dp->dp_read = dap_dp_read_reg; /* For error() use the TARGETID switching firmware_swdp_error */ dp->low_access = dap_dp_low_access; diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 1732e9d9..e3d53e0c 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -331,12 +331,8 @@ static uint32_t wait_word(uint8_t *buf, int size, int len, uint8_t *dp_fault) if (buf[1] > DAP_TRANSFER_WAIT) { DEBUG_WARN("dap wait_word reg %x fault %x\n", - cmd_copy[3] & 0x7c, buf[1]); + cmd_copy[3], buf[1]); *dp_fault = 1; - if (buf[1] == DAP_TRANSFER_ERROR) { - DEBUG_WARN("dap_read_reg, protocoll error\n"); - dap_line_reset(); - } return 0; } uint32_t res = diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 73e019dc..7565d241 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -92,8 +92,8 @@ int adiv5_swdp_scan(uint32_t targetid) initial_dp->seq_out(0x1a0, 12); uint32_t idcode = 0; volatile uint32_t target_id; - bool is_v2 = true; - if (!targetid || (initial_dp->error != firmware_swdp_error)) { + bool scan_multidrop = true; + if (!targetid || !initial_dp->dp_low_write) { /* No targetID given on the command line or probe can not * handle multi-drop. Try to read ID */ dp_line_reset(initial_dp); @@ -102,7 +102,7 @@ int adiv5_swdp_scan(uint32_t targetid) idcode = initial_dp->dp_read(initial_dp, ADIV5_DP_IDCODE); } if (e.type || initial_dp->fault) { - is_v2 = false; + scan_multidrop = false; DEBUG_WARN("Trying old JTAG to SWD sequence\n"); initial_dp->seq_out(0xFFFFFFFF, 32); initial_dp->seq_out(0xFFFFFFFF, 32); @@ -119,7 +119,7 @@ int adiv5_swdp_scan(uint32_t targetid) } } if ((idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { - is_v2 = true; + scan_multidrop = true; /* Read TargetID. Can be done with device in WFI, sleep or reset!*/ adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, 2); target_id = adiv5_dp_read(initial_dp, ADIV5_DP_CTRLSTAT); @@ -131,21 +131,21 @@ int adiv5_swdp_scan(uint32_t targetid) adiv5_dp_write(initial_dp, ADIV5_DP_CTRLSTAT, 0); break; } - if (initial_dp->error != firmware_swdp_error) { + if (!initial_dp->dp_low_write) { DEBUG_WARN("CMSIS_DAP < V1.2 can not handle multi-drop!\n"); /* E.g. CMSIS_DAP < V1.2 can not handle multi-drop!*/ - is_v2 = false; + scan_multidrop = false; } } else { - is_v2 = false; + scan_multidrop = false; } } else { target_id = targetid; } - volatile int nr_dps = (is_v2) ? 16: 1; + volatile int nr_dps = (scan_multidrop) ? 16: 1; volatile uint32_t dp_targetid; for (volatile int i = 0; i < nr_dps; i++) { - if (is_v2) { + if (scan_multidrop) { dp_line_reset(initial_dp); dp_targetid = (i << 28) | (target_id & 0x0fffffff); initial_dp->dp_low_write(initial_dp, ADIV5_DP_TARGETSEL, @@ -158,7 +158,7 @@ int adiv5_swdp_scan(uint32_t targetid) continue; } } else { - dp_targetid = 0; + dp_targetid = target_id; } ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); if (!dp) { /* calloc failed: heap exhaustion */ From 88e44d1c12425bd5443b4a93397d327adf10ee09 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 24 Oct 2021 01:14:46 +0200 Subject: [PATCH 25/31] cmsis: use exception in wait_word(). --- src/platforms/hosted/dap.c | 8 +++++--- src/target/adiv5.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index e3d53e0c..196ed7c6 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -32,6 +32,7 @@ /*- Includes ----------------------------------------------------------------*/ #include +#include "exception.h" #include "dap.h" #include "jtag_scan.h" @@ -329,12 +330,13 @@ static uint32_t wait_word(uint8_t *buf, int size, int len, uint8_t *dp_fault) break; } while (buf[1] == DAP_TRANSFER_WAIT); - if (buf[1] > DAP_TRANSFER_WAIT) { - DEBUG_WARN("dap wait_word reg %x fault %x\n", - cmd_copy[3], buf[1]); + if(buf[1] == SWDP_ACK_FAULT) { *dp_fault = 1; return 0; } + + if(buf[1] != SWDP_ACK_OK) + raise_exception(EXCEPTION_ERROR, "SWDP invalid ACK"); uint32_t res = ((uint32_t)buf[5] << 24) | ((uint32_t)buf[4] << 16) | ((uint32_t)buf[3] << 8) | (uint32_t)buf[2]; diff --git a/src/target/adiv5.h b/src/target/adiv5.h index 63abecf4..95c62f62 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -170,7 +170,7 @@ typedef struct ADIv5_DP_s { void (*seq_out_parity)(uint32_t MS, int ticks); uint32_t (*seq_in)(int ticks); bool (*seq_in_parity)(uint32_t *ret, int ticks); - /* dp_low_write returns true if no OK resonse. */ + /* dp_low_write returns true if no OK resonse, but ignores errors */ bool (*dp_low_write)(struct ADIv5_DP_s *dp, uint16_t addr, const uint32_t data); uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint16_t addr); From 07b4e5726e45b119cb33b4017d291a7f5b4a0e78 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 24 Oct 2021 17:00:58 +0200 Subject: [PATCH 26/31] CMSIS-DAP: Run time detect DAP_SWD_SEQUENCE Some dongles in the making like orbtrace may not yet support. --- src/platforms/hosted/cmsis_dap.c | 10 +++++----- src/platforms/hosted/dap.c | 11 +++++++++++ src/platforms/hosted/dap.h | 1 + 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 1a428525..5c1f2de8 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -251,14 +251,14 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) } res = transferred; } - if (buffer[0] != cmd) { - DEBUG_WARN("cmd %02x invalid response received %02x\n", - cmd, buffer[0]); - } DEBUG_WIRE("cmd res:"); for(int i = 0; (i < 16) && (i < size + 1); i++) DEBUG_WIRE("%02x.", buffer[i]); DEBUG_WIRE("\n"); + if (buffer[0] != cmd) { + DEBUG_WARN("cmd %02x not implemented\n", cmd); + buffer[1] = 0xff /*DAP_ERROR*/; + } if (size) memcpy(data, &buffer[1], (size < res) ? size : res); return res; @@ -453,7 +453,7 @@ int dap_swdptap_init(ADIv5_DP_t *dp) dap_connect(false); dap_led(0, 1); dap_reset_link(false); - if (has_swd_sequence) { + if ((has_swd_sequence) && dap_sequence_test()) { /* DAP_SWD_SEQUENCE does not do auto turnaround, use own!*/ dp->dp_low_write = dap_dp_low_write; } else { diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 196ed7c6..cc58031c 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -793,6 +793,17 @@ void dap_swdptap_seq_out_parity(uint32_t MS, int ticks) DEBUG_WARN("dap_swdptap_seq_out error\n"); } +bool dap_sequence_test(void) +{ + uint8_t buf[4] = { + ID_DAP_SWD_SEQUENCE, + 1, + 0 /* one idle cycle */ + }; + dbg_dap_cmd(buf, sizeof(buf), 3); + return (buf[0] == DAP_OK); +} + #define SWD_SEQUENCE_IN 0x80 uint32_t dap_swdptap_seq_in(int ticks) { diff --git a/src/platforms/hosted/dap.h b/src/platforms/hosted/dap.h index 5d655d85..ac239c9e 100644 --- a/src/platforms/hosted/dap.h +++ b/src/platforms/hosted/dap.h @@ -93,4 +93,5 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, 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); +bool dap_sequence_test(void); #endif // _DAP_H_ From 181466549b6c2f878fcd24ee9faad35a8e4a0f1e Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 27 Oct 2021 01:11:09 +0200 Subject: [PATCH 27/31] adiv5: Progressive incrementing TRNCNT for the DHCSR write when trying to halt Workaround for CMSIS-DAP/Bulk debugger orbtrace that returns NO_ACK with high values of TRNCNT. Perhaps only STM32F767 needs write to DHCSR with high occupancy to catch the device in a moment not sleeping. --- src/target/adiv5.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index a257175a..403ecc99 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -329,13 +329,26 @@ static uint32_t cortexm_initial_halt(ADIv5_AP_t *ap) adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD); adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR); } + /* Workaround for CMSIS-DAP Bulk orbtrace + * High values of TRNCNT lead to NO_ACK answer from debugger. + * + * However CMSIS/HID even with highest value has few chances to catch + * a STM32F767 mostly sleeping in WFI! + */ + uint32_t start_time = platform_time_ms(); + int trncnt = 0x80; while (!platform_timeout_is_expired(&to)) { uint32_t dhcsr ; if (use_low_access) { adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_DP_CTRLSTAT, - ctrlstat | (0xfff * ADIV5_DP_CTRLSTAT_TRNCNT)); + ctrlstat | (trncnt * ADIV5_DP_CTRLSTAT_TRNCNT)); adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DRW, dhcsr_ctl); + if (trncnt < 0xfff) { + trncnt += (platform_time_ms() - start_time) * 8; + } else { + trncnt = 0xfff; + } dhcsr = adiv5_dp_low_access( ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); } else { From a4caec29b9bf1efa80b4beb7d0b0d153fa2c82de Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 31 Oct 2021 10:52:18 +0100 Subject: [PATCH 28/31] dap_swdptap_seq_out: Write only needed data Dragonprobe (origin/cmsisdap-fixes, 211031) hanged on additional byes in the SWJ_Sequence request. --- src/platforms/hosted/dap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index cc58031c..39318b31 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -764,7 +764,7 @@ int dap_jtag_configure(void) void dap_swdptap_seq_out(uint32_t MS, int ticks) { - uint8_t buf[] = { + uint8_t buf[64] = { ID_DAP_SWJ_SEQUENCE, ticks, (MS >> 0) & 0xff, @@ -772,7 +772,7 @@ void dap_swdptap_seq_out(uint32_t MS, int ticks) (MS >> 16) & 0xff, (MS >> 24) & 0xff }; - dbg_dap_cmd(buf, 1, sizeof(buf)); + dbg_dap_cmd(buf, 64, 2 + ((ticks +7) >> 3)); if (buf[0]) DEBUG_WARN("dap_swdptap_seq_out error\n"); } From 2bc2db114011ab140758e17660d2c9f3aaeca7ff Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 31 Oct 2021 12:19:54 +0100 Subject: [PATCH 29/31] cmsis_da: Add timeout to bulk commands. --- src/platforms/hosted/cmsis_dap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 5c1f2de8..c2c5e679 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -241,11 +241,11 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) } else if (type == CMSIS_TYPE_BULK) { int transferred = 0; - res = libusb_bulk_transfer(usb_handle, out_ep, buffer + 1, rsize, &transferred, 0); + res = libusb_bulk_transfer(usb_handle, out_ep, data, rsize, &transferred, 500); if (res < 0) { DEBUG_WARN( "OUT error\n" ); } - res = libusb_bulk_transfer(usb_handle, in_ep, buffer, report_size, &transferred, 0); + res = libusb_bulk_transfer(usb_handle, in_ep, buffer, report_size, &transferred, 500); if (res < 0) { DEBUG_WARN( "IN error\n" ); } From 8970160f1d60149fc72d5d69320a77d641cb4d97 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 31 Oct 2021 12:33:43 +0100 Subject: [PATCH 30/31] cmsis_dap: Timeout and start of error handling for bulk transfers. --- src/platforms/hosted/cmsis_dap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index c2c5e679..761f9351 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -243,11 +243,13 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize) res = libusb_bulk_transfer(usb_handle, out_ep, data, rsize, &transferred, 500); if (res < 0) { - DEBUG_WARN( "OUT error\n" ); + DEBUG_WARN("OUT error: %d\n", res); + return res; } res = libusb_bulk_transfer(usb_handle, in_ep, buffer, report_size, &transferred, 500); if (res < 0) { - DEBUG_WARN( "IN error\n" ); + DEBUG_WARN("IN error: %d\n", res); + return res; } res = transferred; } From 1d0e45bdbba88107e809ec958602eefcec9fc0b3 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 31 Oct 2021 11:07:07 +0100 Subject: [PATCH 31/31] cmsis_dap: Transfersize of block commands needs to cope with word. Checkme: Dragonprobe bulk hangs on transfers with 15 words. --- src/platforms/hosted/cmsis_dap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 761f9351..dd5d3d11 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -279,7 +279,7 @@ static void dap_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len) return dap_read_single(ap, dest, src, align); /* One word transfer for every byte/halfword/word * Total number of bytes in transfer*/ - unsigned int max_size = (dbg_get_report_size() - 5) >> (2 - align); + unsigned int max_size = ((dbg_get_report_size() - 6) >> (2 - align)) & ~3; while (len) { dap_ap_mem_access_setup(ap, src, align); /* Calculate length until next access setup is needed */ @@ -316,7 +316,7 @@ static void dap_mem_write_sized( dest, len, align, *(uint32_t *)src); if (((unsigned)(1 << align)) == len) return dap_write_single(ap, dest, src, align); - unsigned int max_size = (dbg_get_report_size() - 5) >> (2 - align); + unsigned int max_size = ((dbg_get_report_size() - 6) >> (2 - align) & ~3); while (len) { dap_ap_mem_access_setup(ap, dest, align); unsigned int blocksize = (dest | 0x3ff) - dest + 1;