diff --git a/src/crc32.c b/src/crc32.c index 63e37293..a56b9944 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -20,6 +20,7 @@ #include "general.h" #include "target.h" +#include "gdb_if.h" #if !defined(STM32F0) && !defined(STM32F1) && !defined(STM32F2) && \ !defined(STM32F3) && !defined(STM32F4) && !defined(STM32F7) && \ @@ -97,14 +98,31 @@ static uint32_t crc32_calc(uint32_t crc, uint8_t data) return (crc << 8) ^ crc32_table[((crc >> 24) ^ data) & 255]; } -uint32_t generic_crc32(target *t, uint32_t base, size_t len) +int generic_crc32(target *t, uint32_t *crc_res, uint32_t base, size_t len) { uint32_t crc = -1; +#if PC_HOSTED == 1 + /* Reading a 2 MByte on a H743 takes about 80 s@128, 28s @ 1k, + * 22 s @ 4k and 21 s @ 64k + */ + uint8_t bytes[0x1000]; + uint32_t start_time = platform_time_ms(); +#else uint8_t bytes[128]; - +#endif + uint32_t last_time = platform_time_ms(); while (len) { + uint32_t actual_time = platform_time_ms(); + if ( actual_time > last_time + 1000) { + last_time = actual_time; + gdb_if_putchar(0, true); + } size_t read_len = MIN(sizeof(bytes), len); - target_mem_read(t, bytes, base, read_len); + if (target_mem_read(t, bytes, base, read_len)) { + DEBUG_WARN("generic_crc32 error around address 0x%08" PRIx32 "\n", + base); + return -1; + } for (unsigned i = 0; i < read_len; i++) crc = crc32_calc(crc, bytes[i]); @@ -112,20 +130,32 @@ uint32_t generic_crc32(target *t, uint32_t base, size_t len) base += read_len; len -= read_len; } - return crc; + DEBUG_WARN("%d ms\n", platform_time_ms() - start_time); + *crc_res = crc; + return 0; } #else #include -uint32_t generic_crc32(target *t, uint32_t base, size_t len) +int generic_crc32(target *t, uint32_t *crc_res, uint32_t base, size_t len) { uint8_t bytes[128]; uint32_t crc; CRC_CR |= CRC_CR_RESET; + uint32_t last_time = platform_time_ms(); while (len > 3) { + uint32_t actual_time = platform_time_ms(); + if ( actual_time > last_time + 1000) { + last_time = actual_time; + gdb_if_putchar(0, true); + } size_t read_len = MIN(sizeof(bytes), len) & ~3; - target_mem_read(t, bytes, base, read_len); + if (target_mem_read(t, bytes, base, read_len)) { + DEBUG_WARN("generic_crc32 error around address 0x%08" PRIx32 "\n", + base); + return -1; + } for (unsigned i = 0; i < read_len; i += 4) CRC_DR = __builtin_bswap32(*(uint32_t*)(bytes+i)); @@ -136,7 +166,11 @@ uint32_t generic_crc32(target *t, uint32_t base, size_t len) crc = CRC_DR; - target_mem_read(t, bytes, base, len); + if (target_mem_read(t, bytes, base, len)) { + DEBUG_WARN("generic_crc32 error around address 0x%08" PRIx32 "\n", + base); + return -1; + } uint8_t *data = bytes; while (len--) { crc ^= *data++ << 24; @@ -147,7 +181,8 @@ uint32_t generic_crc32(target *t, uint32_t base, size_t len) crc <<= 1; } } - return crc; + *crc_res = crc; + return 0; } #endif diff --git a/src/gdb_main.c b/src/gdb_main.c index 19bcc31a..d453338e 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -412,7 +412,12 @@ handle_q_packet(char *packet, int len) gdb_putpacketz("E01"); return; } - gdb_putpacket_f("C%lx", generic_crc32(cur_target, addr, alen)); + uint32_t crc; + int res = generic_crc32(cur_target, &crc, addr, alen); + if (res) + gdb_putpacketz("E03"); + else + gdb_putpacket_f("C%lx", crc); } else { DEBUG_GDB("*** Unsupported packet: %s\n", packet); diff --git a/src/include/crc32.h b/src/include/crc32.h index 4e0f7291..7d9c65a9 100644 --- a/src/include/crc32.h +++ b/src/include/crc32.h @@ -21,6 +21,6 @@ #ifndef __CRC32_H #define __CRC32_H -uint32_t generic_crc32(target *t, uint32_t base, int len); +int generic_crc32(target *t, uint32_t *crc, uint32_t base, int len); #endif diff --git a/src/include/gdb_if.h b/src/include/gdb_if.h index eed1b9a5..e301bdbf 100644 --- a/src/include/gdb_if.h +++ b/src/include/gdb_if.h @@ -29,6 +29,8 @@ void gdb_usb_out_cb(usbd_device *dev, uint8_t ep); int gdb_if_init(void); unsigned char gdb_if_getchar(void); unsigned char gdb_if_getchar_to(int timeout); + +/* sending gdb_if_putchar(0, true) seems to work as keep alive */ void gdb_if_putchar(unsigned char c, int flush); #endif diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index b1322358..1aebd811 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -1,3 +1,4 @@ +CC ?= gcc SYS = $(shell $(CC) -dumpmachine) CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG CFLAGS +=-I ./target -I./platforms/pc diff --git a/src/platforms/hosted/Readme.md b/src/platforms/hosted/Readme.md index a1d56c5e..aa0d45b7 100644 --- a/src/platforms/hosted/Readme.md +++ b/src/platforms/hosted/Readme.md @@ -1,6 +1,6 @@ # PC-Hosted BMP Compile in src with "make PROBE_HOST=hosted". This needs minimal external -support. "make PROBE_HOST=hosted HOSTED_BMP=0" will compile support for FTDI, +support. "make PROBE_HOST=hosted HOSTED_BMP_ONLY=0" will compile support for FTDI, STLink, CMSIS-DAP and JLINK probes, but requires external libraries. ## Description @@ -94,7 +94,7 @@ REMOTE_BMP is a "normal" BMP usb connected | Debugger | Speed | Remarks | ------------ | ----- | ------ | REMOTE_BMP | +++ | Requires recent firmware for decent speed -Probes below only when compiled with HOSTED_BMP=0 +Probes below only when compiled with HOSTED_BMP_ONLY=0 | ST-Link V3 | ++++ | Requires recent firmware, Only STM32 devices supported! | ST-Link V2 | +++ | Requires recent firmware, No CDCACM uart! Cortex only! | ST-Link V2/1 | +++ | Requires recent firmware, Cortex only! diff --git a/src/platforms/hosted/bmp_serial.c b/src/platforms/hosted/bmp_serial.c index c04807b9..c6d3e52b 100644 --- a/src/platforms/hosted/bmp_serial.c +++ b/src/platforms/hosted/bmp_serial.c @@ -39,6 +39,7 @@ void libusb_exit_function(bmp_info_t *info) {(void)info;}; #ifdef __APPLE__ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) { + DEBUG_WARN("Please implement find_debuggers for MACOS!\n"); (void)cl_opts; (void)info; return -1; diff --git a/src/platforms/hosted/ftdi_bmp.c b/src/platforms/hosted/ftdi_bmp.c index 7d515f1c..370f9782 100644 --- a/src/platforms/hosted/ftdi_bmp.c +++ b/src/platforms/hosted/ftdi_bmp.c @@ -552,8 +552,8 @@ void libftdi_jtagtap_tdi_tdo_seq( if(!ticks) return; if (!DI && !DO) return; - DEBUG_WIRE("libftdi_jtagtap_tdi_tdo_seq %s ticks: %d\n", - (DI && DO) ? "read/write" : ((DI) ? "read" : "write"),ticks); + DEBUG_WIRE("libftdi_jtagtap_tdi_tdo_seq %s ticks: %d\n", + (DI && DO) ? "read/write" : ((DI) ? "write" : "read"), ticks); if(final_tms) ticks--; rticks = ticks & 7; ticks >>= 3; diff --git a/src/platforms/hosted/remote_jtagtap.c b/src/platforms/hosted/remote_jtagtap.c index a92a253c..a5aa3b6c 100644 --- a/src/platforms/hosted/remote_jtagtap.c +++ b/src/platforms/hosted/remote_jtagtap.c @@ -118,8 +118,6 @@ static void jtagtap_tdi_tdo_seq( if(!ticks || (!DI && !DO)) return; - uint64_t *DIl = (uint64_t *)DI; - uint64_t *DOl = (uint64_t *)DO; while (ticks) { int chunk; if (ticks < 65) @@ -128,19 +126,26 @@ static void jtagtap_tdi_tdo_seq( chunk = 64; } ticks -= chunk; - uint64_t dil; - if (DI) - dil = *DIl++; - else - dil = 0; - /* Reduce the length of DI according to the bits we're transmitting */ - if (chunk < 64) - dil &= ((1LL << chunk) - 1); + uint8_t di[8]; + memset(di, 0, 8); + int bytes = (chunk + 7) >> 3; + if (DI) { + memcpy(&di, DI, bytes); + int remainder = chunk & 7; + DI += bytes; + DI += bytes; + if (remainder) { + uint8_t rem = *DI; + rem &= (1 << remainder) - 1; + *di = rem; + } + }; + /* PRIx64 differs with system. Use it explicit in the format string*/ s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "!J%c%02x%" PRIx64 "%c", (!ticks && final_tms) ? REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS, - chunk, dil, REMOTE_EOM); + chunk, *(uint64_t*)di, REMOTE_EOM); platform_buffer_write(construct,s); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); @@ -149,8 +154,11 @@ static void jtagtap_tdi_tdo_seq( s ? (char *)&(construct[1]) : "unknown"); exit(-1); } - if (DO) - *DOl++ = remotehston(-1, (char *)&construct[1]); + if (DO) { + uint64_t res = remotehston(-1, (char *)&construct[1]); + memcpy(DO, &res, bytes); + DO += bytes; + } } } diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 65de1cf9..6bdba898 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -522,7 +522,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) if ((opt->opt_mode == BMP_MODE_FLASH_READ) || (opt->opt_mode == BMP_MODE_FLASH_VERIFY) || (opt->opt_mode == BMP_MODE_FLASH_WRITE_VERIFY)) { -#define WORKSIZE 1024 +#define WORKSIZE 0x1000 uint8_t *data = alloca(WORKSIZE); if (!data) { DEBUG_WARN("Can not malloc memory for flash read/verify " diff --git a/src/platforms/pc/utils.c b/src/platforms/pc/utils.c index e5de7148..5bc27b7f 100644 --- a/src/platforms/pc/utils.c +++ b/src/platforms/pc/utils.c @@ -50,7 +50,7 @@ void platform_delay(uint32_t ms) # if !defined(usleep) int usleep(unsigned int); # endif - usleep(ms); + usleep(ms * 1000); #endif } diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 1994ea67..e6ecb41a 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -308,6 +308,68 @@ uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr) return pidr; } +/* Halt CortexM + * + * Run in tight loop to catch small windows of awakeness. + * Repeat the write command with the highest possible value + * of the trannsaction counter, if not on MINDP + */ +static uint32_t cortexm_initial_halt(ADIv5_AP_t *ap) +{ + platform_timeout to ; + uint32_t ctrlstat = adiv5_dp_read(ap->dp, ADIV5_DP_CTRLSTAT); + platform_timeout_set(&to, cortexm_wait_timeout); + uint32_t dhcsr_ctl = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN | + 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 + if (use_low_access) { + DEBUG_WARN("Using low access\n"); + /* 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); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR); + } + while (!platform_timeout_is_expired(&to)) { + uint32_t dhcsr ; + if (use_low_access) { + adiv5_dp_write(ap->dp, ADIV5_DP_CTRLSTAT, + ctrlstat | (0xfff * ADIV5_DP_CTRLSTAT_TRNCNT)); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DRW, + dhcsr_ctl); + dhcsr = adiv5_dp_low_access( + ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); + } else { + adiv5_mem_write(ap, CORTEXM_DHCSR, &dhcsr_ctl, sizeof(dhcsr_ctl)); + dhcsr = adiv5_mem_read32(ap, CORTEXM_DHCSR); + } + /* ADIV5_DP_CTRLSTAT_READOK is always set e.g. on STM32F7 even so + CORTEXM_DHCS reads nonsense*/ + /* On a sleeping STM32F7, invalid DHCSR reads with e.g. 0xffffffff and + * 0x0xA05F0000 may happen. + * M23/33 will have S_SDE set when debug is allowed + */ + if ((dhcsr != 0xffffffff) && /* Invalid read */ + ((dhcsr & 0xf000fff0) == 0)) {/* Check RAZ bits */ + if ((dhcsr & CORTEXM_DHCSR_S_RESET_ST) && !reset_seen) { + if (connect_assert_srst) + return dhcsr; + reset_seen = true; + continue; + } + if ((dhcsr & dhcsr_valid) == dhcsr_valid) { /* Halted */ + return dhcsr; + } + } + } + return 0; +} + /* Prepare to read SYSROM and SYSROM PIDR * * Try hard to halt, if not connecting under reset @@ -329,52 +391,26 @@ uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr) */ static bool cortexm_prepare(ADIv5_AP_t *ap) { - platform_timeout to ; - platform_timeout_set(&to, cortexm_wait_timeout); - uint32_t dhcsr_ctl = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN | - CORTEXM_DHCSR_C_HALT; - uint32_t dhcsr_valid = CORTEXM_DHCSR_S_HALT | CORTEXM_DHCSR_C_DEBUGEN; -#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG) +#if PC_HOSTED == 1 uint32_t start_time = platform_time_ms(); #endif - uint32_t dhcsr; - bool reset_seen = false; - while (true) { - adiv5_mem_write(ap, CORTEXM_DHCSR, &dhcsr_ctl, sizeof(dhcsr_ctl)); - dhcsr = adiv5_mem_read32(ap, CORTEXM_DHCSR); - /* ADIV5_DP_CTRLSTAT_READOK is always set e.g. on STM32F7 even so - CORTEXM_DHCS reads nonsense*/ - /* On a sleeping STM32F7, invalid DHCSR reads with e.g. 0xffffffff and - * 0x0xA05F0000 may happen. - * M23/33 will have S_SDE set when debug is allowed - */ - if ((dhcsr != 0xffffffff) && /* Invalid read */ - ((dhcsr & 0xf000fff0) == 0)) {/* Check RAZ bits */ - if ((dhcsr & CORTEXM_DHCSR_S_RESET_ST) && !reset_seen) { - if (connect_assert_srst) - break; - reset_seen = true; - continue; - } - if ((dhcsr & dhcsr_valid) == dhcsr_valid) { /* Halted */ - DEBUG_INFO("Halt via DHCSR: success %08" PRIx32 " after %" - PRId32 "ms\n", - dhcsr, platform_time_ms() - start_time); - break; - } - } - if (platform_timeout_is_expired(&to)) { - DEBUG_WARN("Halt via DHCSR: Failure DHCSR %08" PRIx32 " after % " - PRId32 "ms\nTry again, evt. with longer timeout or " - "connect under reset\n", - dhcsr, platform_time_ms() - start_time); - return false; - } + uint32_t dhcsr = cortexm_initial_halt(ap); + if (!dhcsr) { + DEBUG_WARN("Halt via DHCSR: Failure DHCSR %08" PRIx32 " after % " + PRId32 "ms\nTry again, evt. with longer timeout or " + "connect under reset\n", + adiv5_mem_read32(ap, CORTEXM_DHCSR), + platform_time_ms() - start_time); + return false; } + DEBUG_INFO("Halt via DHCSR: success %08" PRIx32 " after %" PRId32 "ms\n", + dhcsr, + platform_time_ms() - start_time); ap->ap_cortexm_demcr = adiv5_mem_read32(ap, CORTEXM_DEMCR); uint32_t demcr = CORTEXM_DEMCR_TRCENA | CORTEXM_DEMCR_VC_HARDERR | CORTEXM_DEMCR_VC_CORERESET; adiv5_mem_write(ap, CORTEXM_DEMCR, &demcr, sizeof(demcr)); + platform_timeout to ; platform_timeout_set(&to, cortexm_wait_timeout); platform_srst_set_val(false); while (1) { @@ -658,7 +694,8 @@ void adiv5_dp_init(ADIv5_DP_t *dp) } DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%d %srev%d)\n", dp->idcode, (uint8_t)((dp->idcode >> 12) & 0xf), - (dp->idcode & 0x10000) ? "MINDP " : "", (uint16_t)(dp->idcode >> 28)); + (dp->idcode & ADIV5_MINDP) ? "MINDP " : "", + (uint16_t)(dp->idcode >> 28)); volatile uint32_t ctrlstat = 0; #if PC_HOSTED == 1 platform_adiv5_dp_defaults(dp); diff --git a/src/target/adiv5.h b/src/target/adiv5.h index 2c58d02b..c8b77cc1 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -45,6 +45,7 @@ #define ADIV5_DP_VERSION_MASK 0xf000 #define ADIV5_DPv1 0x1000 #define ADIV5_DPv2 0x2000 +#define ADIV5_MINDP 0x10000 /* AP Abort Register (ABORT) */ /* Bits 31:5 - Reserved */ @@ -64,7 +65,7 @@ #define ADIV5_DP_CTRLSTAT_CDBGRSTREQ (1u << 26) /* Bits 25:24 - Reserved */ /* Bits 23:12 - TRNCNT */ -#define ADIV5_DP_CTRLSTAT_TRNCNT +#define ADIV5_DP_CTRLSTAT_TRNCNT (1u << 12) /* Bits 11:8 - MASKLANE */ #define ADIV5_DP_CTRLSTAT_MASKLANE /* Bits 7:6 - Reserved in JTAG-DP */ @@ -189,7 +190,6 @@ typedef struct ADIv5_DP_s { void (*read_block)(uint32_t addr, uint8_t *data, int size); void (*dap_write_block_sized)(uint32_t addr, uint8_t *data, int size, enum align align); - #endif uint32_t (*ap_read)(ADIv5_AP_t *ap, uint16_t addr); void (*ap_write)(ADIv5_AP_t *ap, uint16_t addr, uint32_t value); diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 22551580..de400d06 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -325,13 +325,45 @@ bool kinetis_probe(target *t) 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; + /* gen1 s32k14x */ + { + uint32_t sram_l, sram_h; + uint32_t flash, flexmem; + case 0x142: /* s32k142 */ + case 0x143: /* s32k142w */ + sram_l = 0x1FFFC000; /* SRAM_L, 16k */ + sram_h = 0x03000; /* SRAM_H, 12k */ + flash = 0x00040000; /* flash 256 KB */ + flexmem = 0x10000; /* FlexNVM 64 KB */ + goto do_common_s32k14x; + case 0x144: /* s32k144 */ + case 0x145: /* s32k144w */ + sram_l = 0x1FFF8000; /* SRAM_L, 32k */ + sram_h = 0x07000; /* SRAM_H, 28k */ + flash = 0x00080000; /* flash 512 KB */ + flexmem = 0x10000; /* FlexNVM 64 KB */ + goto do_common_s32k14x; + case 0x146: /* s32k146 */ + sram_l = 0x1fff0000; /* SRAM_L, 64k */ + sram_h = 0x0f000; /* SRAM_H, 60k */ + flash = 0x00100000; /* flash 1024 KB */ + flexmem = 0x10000; /* FlexNVM 64 KB */ + goto do_common_s32k14x; case 0x148: /* S32K148 */ - t->driver = "S32K148"; - target_add_ram(t, 0x1FFE0000, 0x20000); /* SRAM_L, 128 KB */ - target_add_ram(t, 0x20000000, 0x1f000); /* SRAM_H, 124 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00180000, 0x1000, K64_WRITE_LEN); /* P-Flash, 1536 KB, 4 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, 0x80000, 0x1000, K64_WRITE_LEN); /* FlexNVM, 512 KB, 4 KB Sectors */ + sram_l = 0x1ffe0000; /* SRAM_L, 128 KB */ + sram_h = 0x1f000; /* SRAM_H, 124 KB */ + flash = 0x00180000; /* flash 1536 KB */ + flexmem = 0x80000; /* FlexNVM 512 KB */ + goto do_common_s32k14x; +do_common_s32k14x: + t->driver = "S32K14x"; + target_add_ram(t, sram_l, 0x20000000 - sram_l); + target_add_ram(t, 0x20000000, sram_h); + + kl_gen_add_flash(t, 0x00000000, flash, 0x1000, K64_WRITE_LEN); /* P-Flash, 4 KB Sectors */ + kl_gen_add_flash(t, 0x10000000, flexmem, 0x1000, K64_WRITE_LEN); /* FlexNVM, 4 KB Sectors */ break; + } default: return false; } diff --git a/src/target/lpc_common.c b/src/target/lpc_common.c index f70c0d6e..37acce83 100644 --- a/src/target/lpc_common.c +++ b/src/target/lpc_common.c @@ -151,7 +151,7 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd #if defined(ENABLE_DEBUG) if (param.status != IAP_STATUS_CMD_SUCCESS) { if (param.status > (sizeof(iap_error) / sizeof(char*))) - DEBUG_WARN("IAP cmd %d : %d\n", cmd, param.status); + DEBUG_WARN("IAP cmd %d : %" PRId32 "\n", cmd, param.status); else DEBUG_WARN("IAP cmd %d : %s\n", cmd, iap_error[param.status]); DEBUG_WARN("return parameters: %08" PRIx32 " %08" PRIx32 " %08" PRIx32