diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..cc80d9c8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,40 @@ +# Text for humans +LICENSE text eol=lf +HACKING text eol=lf +COPYING text eol=lf +UsingSWO text eol=lf +README.* text eol=lf + +# Source code +Makefile text eol=lf +*.mk text eol=lf +*.mak text eol=lf +*.inc text eol=lf +*.py text eol=lf +*.sh text eol=lf +*.c text eol=lf +*.S text eol=lf +*.s text eol=lf +*.h text eol=lf +*.ld text eol=lf +*.yml text eol=lf +*.rules text eol=lf + +# Git control files +.gitattributes eol=lf +.gitignore eol=lf +.gitmodules eol=lf + +# Windows source code uses CRLF +*.vcxproj text eol=crlf +*.props text eol=crlf +*.bat text eol=crlf +*.ps1 text eol=crlf +*.inf text eol=crlf + +# Other binary files +*.png binary +*.jpg binary +*.bin binary +*.elf binary +*.bin binary diff --git a/.gitignore b/.gitignore index 48d1ae72..7a6a0999 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ blackmagic_upgrade .vscode cscope.out cscope.files +.gdb_history +src/artifacts/ \ No newline at end of file diff --git a/UsingSWO b/UsingSWO index a9d8ee16..d8ad984b 100644 --- a/UsingSWO +++ b/UsingSWO @@ -14,24 +14,28 @@ monitor traceswo 115200 We are constrained on maximum input speed by both the capabilities of the BMP STM32F103 USART and the ability to get the packets back out over the USB -link. The UART baudrate is set by b=(72x10^6)/(16*d)...so for d=1 that means -a maximum speed of 4.5Mbps. For continious streaming that turns out to be -_too_ fast for the USB link, so the next available option is the 2.25Mbps -that we use. ....you can safely use the 4.5Mbps setting if your debug data +link. The UART baudrate is set by b=(72x10^6)/d...with d >= 16 or +a maximum speed of 4.5Mbps UART1 and 2.25 Mbps on UART2. +For continious streaming that turns out to be_too_ fast for the USB +link, so the next available option is the 2.25Mbps that we use. .... +You can safely use the 4.5Mbps setting if your debug data is bursty, or if you're using a different CPU to the STM32F103 as your BMP host, but you potentially run the risk of losing packets if you have long runs of sending which the usb cannot flush in time (there's a 12K buffer, so the it is a pretty long run before it becomes a problem). Note that the baudrate equation means there are only certain speeds -available. The highest half dozen are; -SWO uses USART1(stlink) USART2(swlink) -1 4.50 Mbps 2.25 Mbps -2 2.25 Mbps 1.125 Mbps -3 1.50 Mbps 0.75 Mbps -4 1.125 Mbps 0.5635 Mbps -5 0.900 Mbps 0.45 Mbps -6 0.750 Mbps 0.375 Mbps +available. The highest: +BRR USART1(stlink) USART2(swlink) +16 4.50 Mbps 2.25 Mbps +17 4.235 Mbps 2.118 Mbps +18 4.000 Mbps 2.0 Mbps +19 3.789 Mbps 1.895 Mbps +20 3.600 Mbps 1.8 Mbps +... +24 3.0 Mbps 1.5 Mbps +... +36 2.0 Mbps 1.0 Mbps ...the USART will cope with some timing slip, but it's advisible to stay as close to these values as you can. As the speed comes down the spread between diff --git a/src/command.c b/src/command.c index 9eec7fbc..c1c18952 100644 --- a/src/command.c +++ b/src/command.c @@ -3,6 +3,8 @@ * * Copyright (C) 2011 Black Sphere Technologies Ltd. * Written by Gareth McMullin + * Copyright (C) 2021 Uwe Bonnes + * (bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +29,7 @@ #include "command.h" #include "gdb_packet.h" #include "target.h" +#include "target_internal.h" #include "morse.h" #include "version.h" #include "serialno.h" @@ -37,13 +40,6 @@ typedef bool (*cmd_handler)(target *t, int argc, const char **argv); -struct command_s { - const char *cmd; - cmd_handler handler; - - const char *help; -}; - static bool cmd_version(target *t, int argc, char **argv); static bool cmd_serial(target *t, int argc, char **argv); static bool cmd_help(target *t, int argc, char **argv); @@ -179,10 +175,11 @@ bool cmd_help(target *t, int argc, char **argv) (void)argv; const struct command_s *c; - gdb_out("General commands:\n"); - for(c = cmd_list; c->cmd; c++) - gdb_outf("\t%s -- %s\n", c->cmd, c->help); - + if (!t || t->tc->destroy_callback) { + gdb_out("General commands:\n"); + for(c = cmd_list; c->cmd; c++) + gdb_outf("\t%s -- %s\n", c->cmd, c->help); + } if (!t) return -1; @@ -240,8 +237,9 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv) bool cmd_swdp_scan(target *t, int argc, char **argv) { (void)t; - (void)argc; - (void)argv; + volatile uint32_t targetid = 0; + if (argc > 1) + targetid = strtol(argv[1], NULL, 0); if (platform_target_voltage()) gdb_outf("Target voltage: %s\n", platform_target_voltage()); @@ -252,9 +250,9 @@ bool cmd_swdp_scan(target *t, int argc, char **argv) volatile struct exception e; TRY_CATCH (e, EXCEPTION_ALL) { #if PC_HOSTED == 1 - devs = platform_adiv5_swdp_scan(); + devs = platform_adiv5_swdp_scan(targetid); #else - devs = adiv5_swdp_scan(); + devs = adiv5_swdp_scan(targetid); #endif } switch (e.type) { diff --git a/src/include/target.h b/src/include/target.h index 7c71340f..5cf04ac5 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -35,13 +35,13 @@ typedef uint32_t target_addr; struct target_controller; #if PC_HOSTED == 1 -int platform_adiv5_swdp_scan(void); +int platform_adiv5_swdp_scan(uint32_t targetid); int platform_jtag_scan(const uint8_t *lrlens); #endif -int adiv5_swdp_scan(void); +int adiv5_swdp_scan(uint32_t targetid); int jtag_scan(const uint8_t *lrlens); -bool target_foreach(void (*cb)(int i, target *t, void *context), void *context); +int target_foreach(void (*cb)(int i, target *t, void *context), void *context); void target_list_free(void); /* Attach/detach functions */ diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index 4a6c9634..95d0ca9c 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -144,7 +144,7 @@ static const struct usb_interface_descriptor gdb_comm_iface[] = {{ .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_CDC, .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, .iInterface = 4, .endpoint = gdb_comm_endp, @@ -174,7 +174,7 @@ static const struct usb_iface_assoc_descriptor gdb_assoc = { .bInterfaceCount = 2, .bFunctionClass = USB_CLASS_CDC, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .bFunctionProtocol = USB_CDC_PROTOCOL_NONE, .iFunction = 0, }; @@ -247,7 +247,7 @@ static const struct usb_interface_descriptor uart_comm_iface[] = {{ .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_CDC, .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, .iInterface = 5, .endpoint = uart_comm_endp, @@ -277,7 +277,7 @@ static const struct usb_iface_assoc_descriptor uart_assoc = { .bInterfaceCount = 2, .bFunctionClass = USB_CLASS_CDC, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .bFunctionProtocol = USB_CDC_PROTOCOL_NONE, .iFunction = 0, }; @@ -401,8 +401,8 @@ char serial_no[13]; static char serial_no[9]; #endif -#define BOARD_IDENT "Black Magic Probe" PLATFORM_IDENT FIRMWARE_VERSION -#define DFU_IDENT "Black Magic Firmware Upgrade" PLATFORM_IDENT FIRMWARE_VERSION +#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", diff --git a/src/platforms/hosted/Readme.md b/src/platforms/hosted/Readme.md index 13477ddd..5f3e24d1 100644 --- a/src/platforms/hosted/Readme.md +++ b/src/platforms/hosted/Readme.md @@ -36,7 +36,19 @@ blackmagic -V .bin ``` ### Show more options ``` -blackmagic -h" +blackmagic -h +``` +### Show available monitor commands +``` +blackmagic -M help +``` +### Show available monitor commands on second target +``` +blackmagic -n 2 -M help +``` +### Monitor commands with multiple arguments, e.g.Stm32F1: +``` +blackmagic -M "option help" ``` ## Used shared libraries: ### libusb diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index e29344b8..0264f25b 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) + * Copyright(C) 2020 - 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,13 +36,15 @@ #define VENDOR_ID_SEGGER 0x1366 +#define NO_SERIAL_NUMBER "" + void bmp_ident(bmp_info_t *info) { DEBUG_INFO("BMP hosted %s\n for ST-Link V2/3, CMSIS_DAP, JLINK and " "LIBFTDI/MPSSE\n", FIRMWARE_VERSION); if (info && info->vid && info->pid) DEBUG_INFO("Using %04x:%04x %s %s\n %s\n", info->vid, info->pid, - info->serial, + (info->serial[0]) ? info->serial : NO_SERIAL_NUMBER, info->manufacturer, info->product); } @@ -147,22 +149,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) res = libusb_get_string_descriptor_ascii( handle, desc.iManufacturer, (uint8_t*)manufacturer, sizeof(manufacturer)); - if (res > 0) { - res = libusb_get_string_descriptor_ascii( - handle, desc.iProduct, (uint8_t*)product, - sizeof(product)); - if (res <= 0) { - DEBUG_WARN( "WARN:" - "libusb_get_string_descriptor_ascii " - "for ident_string failed: %s\n", - libusb_strerror(res)); - libusb_close(handle); - continue; - } - } else { - libusb_close(handle); - continue; - } + res = libusb_get_string_descriptor_ascii( + handle, desc.iProduct, (uint8_t*)product, + sizeof(product)); libusb_close(handle); if (cl_opts->opt_ident_string) { char *match_manu = NULL; @@ -233,11 +222,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) if (!cable->name) continue; } - if (!serial[0]) - strcpy(serial, ""); if (report) { DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers + 1, - serial, + (serial[0]) ? serial : NO_SERIAL_NUMBER, manufacturer,product); } info->vid = desc.idVendor; diff --git a/src/platforms/hosted/bmp_remote.c b/src/platforms/hosted/bmp_remote.c index 66d1b92a..b8dc1d2e 100644 --- a/src/platforms/hosted/bmp_remote.c +++ b/src/platforms/hosted/bmp_remote.c @@ -73,7 +73,7 @@ bool remote_target_get_power(void) return (construct[1] == '1'); } -void remote_target_set_power(bool power) +bool remote_target_set_power(bool power) { uint8_t construct[REMOTE_MAX_MSG_SIZE]; int s; @@ -87,8 +87,9 @@ void remote_target_set_power(bool power) if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { DEBUG_WARN("platform_target_set_power failed, error %s\n", s ? (char *)&(construct[1]) : "unknown"); - exit(-1); + return false; } + return true; } void remote_srst_set_val(bool assert) diff --git a/src/platforms/hosted/bmp_remote.h b/src/platforms/hosted/bmp_remote.h index c61cb026..cff7563f 100644 --- a/src/platforms/hosted/bmp_remote.h +++ b/src/platforms/hosted/bmp_remote.h @@ -34,7 +34,7 @@ int remote_swdptap_init(swd_proc_t *swd_proc); int remote_jtagtap_init(jtag_proc_t *jtag_proc); bool remote_target_get_power(void); const char *remote_target_voltage(void); -void remote_target_set_power(bool power); +bool remote_target_set_power(bool power); void remote_srst_set_val(bool assert); bool remote_srst_get_val(void); void remote_max_frequency_set(uint32_t freq); diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 06894174..a4056eb0 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2019-20 Uwe Bonnes + * Copyright (C) 2019-2021 Uwe Bonnes * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,10 +49,11 @@ uint8_t mode; static hid_device *handle = NULL; static uint8_t hid_buffer[1024 + 1]; static int report_size = 64 + 1; // TODO: read actual report size +static bool has_swd_sequence = false; + /* LPC845 Breakout Board Rev. 0 report invalid response with > 65 bytes */ int dap_init(bmp_info_t *info) { - DEBUG_INFO("dap_init\n"); if (hid_init()) return -1; int size = strlen(info->serial); @@ -71,17 +72,32 @@ int dap_init(bmp_info_t *info) if (!handle) return -1; dap_disconnect(); + size = dap_info(DAP_INFO_FW_VER, hid_buffer, sizeof(hid_buffer)); + if (size) { + DEBUG_INFO("Ver %s, ", hid_buffer); + int major = -1, minor = -1, sub = -1; + if (sscanf((const char *)hid_buffer, "%d.%d.%d", + &major, &minor, &sub)) { + if (sub == -1) { + if (minor > 10) { + minor /= 10; + sub = 0; + } + } + has_swd_sequence = ((major > 0 ) && (minor > 1)); + } + } size = dap_info(DAP_INFO_CAPABILITIES, hid_buffer, sizeof(hid_buffer)); dap_caps = hid_buffer[0]; - DEBUG_INFO(" Cap (0x%2x): %s%s%s", hid_buffer[0], - (hid_buffer[0] & 1)? "SWD" : "", - ((hid_buffer[0] & 3) == 3) ? "/" : "", - (hid_buffer[0] & 2)? "JTAG" : ""); - if (hid_buffer[0] & 4) + DEBUG_INFO("Cap (0x%2x): %s%s%s", dap_caps, + (dap_caps & 1)? "SWD" : "", + ((dap_caps & 3) == 3) ? "/" : "", + (dap_caps & 2)? "JTAG" : ""); + if (dap_caps & 4) DEBUG_INFO(", SWO_UART"); - if (hid_buffer[0] & 8) + if (dap_caps & 8) DEBUG_INFO(", SWO_MANCHESTER"); - if (hid_buffer[0] & 0x10) + if (dap_caps & 0x10) DEBUG_INFO(", Atomic Cmds"); DEBUG_INFO("\n"); return 0; diff --git a/src/platforms/hosted/ftdi_bmp.h b/src/platforms/hosted/ftdi_bmp.h index ffb9e866..51368194 100644 --- a/src/platforms/hosted/ftdi_bmp.h +++ b/src/platforms/hosted/ftdi_bmp.h @@ -27,7 +27,6 @@ #include "jtagtap.h" #include "bmp_hosted.h" -#include typedef struct data_desc_s { int16_t data_low; @@ -101,11 +100,6 @@ typedef struct cable_desc_s { char * name; }cable_desc_t; -extern cable_desc_t cable_desc[]; -extern cable_desc_t *active_cable; -extern struct ftdi_context *ftdic; -extern data_desc_t active_state; - #if HOSTED_BMP_ONLY == 1 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-parameter" @@ -123,6 +117,12 @@ void libftdi_max_frequency_set(uint32_t freq) {}; uint32_t libftdi_max_frequency_get(void) {return 0;}; # pragma GCC diagnostic pop #else +#include +extern cable_desc_t cable_desc[]; +extern cable_desc_t *active_cable; +extern struct ftdi_context *ftdic; +extern data_desc_t active_state; + int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info); int libftdi_swdptap_init(swd_proc_t *swd_proc); int libftdi_jtagtap_init(jtag_proc_t *jtag_proc); diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 5e55603d..fc4d1011 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) + * Copyright (C) 2020- 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -119,14 +119,16 @@ void platform_init(int argc, char **argv) exit(ret); } -int platform_adiv5_swdp_scan(void) +int platform_adiv5_swdp_scan(uint32_t targetid) { info.is_jtag = false; platform_max_frequency_set(cl_opts.opt_max_swj_frequency); + if (targetid && (info.bmp_type != BMP_TYPE_BMP)) + DEBUG_WARN("Ignoring TARGETID for now!\n"); switch (info.bmp_type) { case BMP_TYPE_BMP: case BMP_TYPE_LIBFTDI: - return adiv5_swdp_scan(); + return adiv5_swdp_scan(targetid); break; case BMP_TYPE_STLINKV2: { @@ -377,6 +379,20 @@ uint32_t platform_max_frequency_get(void) return false; } +void platform_target_set_power(bool power) +{ + switch (info.bmp_type) { + case BMP_TYPE_BMP: + if (remote_target_set_power(power)) + DEBUG_INFO("Powering up device!\n"); + else + DEBUG_WARN("Powering up device unimplemented or failed\n"); + break; + default: + break; + } +} + void platform_buffer_flush(void) { switch (info.bmp_type) { diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 2f6e87f4..798a7f0d 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -131,10 +131,6 @@ void platform_init(void) GPIO_CNF_OUTPUT_PUSHPULL, LED_UART | LED_IDLE_RUN | LED_ERROR); - /* FIXME: This pin in intended to be input, but the TXS0108 fails - * to release the device from reset if this floats. */ - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO7); /* Enable SRST output. Original uses a NPN to pull down, so setting the * output HIGH asserts. Mini is directly connected so use open drain output * and set LOW to assert. @@ -146,7 +142,17 @@ void platform_init(void) ? GPIO_CNF_OUTPUT_PUSHPULL : GPIO_CNF_OUTPUT_OPENDRAIN), SRST_PIN); - + /* FIXME: Gareth, Esden, what versions need this fix? */ + if (platform_hwversion() < 3) { + /* FIXME: This pin in intended to be input, but the TXS0108 fails + * to release the device from reset if this floats. */ + gpio_set_mode(SRST_SENSE_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, SRST_SENSE_PIN); + } else { + gpio_set(SRST_SENSE_PORT, SRST_SENSE_PIN); + gpio_set_mode(SRST_SENSE_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, SRST_SENSE_PIN); + } /* Enable internal pull-up on PWR_BR so that we don't drive TPWR locally or inadvertently supply power to the target. */ if (platform_hwversion () == 1) { diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 78ba5b52..df13c123 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2019 - 2020 Uwe Bonnes + * Copyright (C) 2019 - 2021 Uwe Bonnes * (bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify @@ -32,6 +32,7 @@ #include "target.h" #include "target_internal.h" #include "cortexm.h" +#include "command.h" #include "cl_utils.h" #include "bmp_hosted.h" @@ -45,6 +46,18 @@ # include #endif +static void cl_target_printf(struct target_controller *tc, + const char *fmt, va_list ap) +{ + (void)tc; + + vprintf(fmt, ap); +} + +static struct target_controller cl_controller = { + .printf = cl_target_printf, +}; + struct mmap_data { void *data; size_t size; @@ -152,6 +165,9 @@ static void cl_help(char **argv) DEBUG_WARN("\t-p\t\t: Supplies power to the target (where applicable)\n"); DEBUG_WARN("\t-R\t\t: Reset device\n"); DEBUG_WARN("\t-H\t\t: Do not use high level commands (BMP-Remote)\n"); + DEBUG_WARN("\t-m \t: Use (target)id for SWD multi-drop.\n"); + DEBUG_WARN("\t-M \t: Run target specific monitor commands. Quote multi\n"); + DEBUG_WARN("\t\t\t word strings. Run \"-M help\" for help.\n"); DEBUG_WARN("Flash operation modifiers options:\n"); DEBUG_WARN("\tDefault action with given file is to write to flash\n"); DEBUG_WARN("\t-a \t: Start flash operation at flash address \n" @@ -168,7 +184,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->opt_flash_size = 16 * 1024 *1024; opt->opt_flash_start = 0xffffffff; opt->opt_max_swj_frequency = 4000000; - while((c = getopt(argc, argv, "eEhHv:d:f:s:I:c:CnltVtTa:S:jpP:rR")) != -1) { + while((c = getopt(argc, argv, "eEhHv:d:f:s:I:c:Cln:m:M:tVtTa:S:jpP:rR")) != -1) { switch(c) { case 'c': if (optarg) @@ -255,6 +271,15 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) if (optarg) opt->opt_target_dev = strtol(optarg, NULL, 0); break; + case 'm': + if (optarg) + opt->opt_targetid = strtol(optarg, NULL, 0); + break; + case 'M': + opt->opt_mode = BMP_MODE_MONITOR; + if (optarg) + opt->opt_monitor = optarg; + break; case 'P': if (optarg) opt->opt_position = atoi(optarg); @@ -313,13 +338,10 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) { int res = -1; int num_targets; -#if defined(PLATFORM_HAS_POWER_SWITCH) if (opt->opt_tpwr) { - DEBUG_INFO("Powering up device"); platform_target_set_power(true); platform_delay(500); } -#endif if (opt->opt_connect_under_reset) DEBUG_INFO("Connecting under reset\n"); connect_assert_srst = opt->opt_connect_under_reset; @@ -330,66 +352,52 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) if (opt->opt_usejtag) { num_targets = platform_jtag_scan(NULL); } else { - num_targets = platform_adiv5_swdp_scan(); + num_targets = platform_adiv5_swdp_scan(opt->opt_targetid); } if (!num_targets) { DEBUG_WARN("No target found\n"); return res; } else { - target_foreach(display_target, NULL); + num_targets = target_foreach(display_target, &num_targets); } if (opt->opt_target_dev > num_targets) { - DEBUG_WARN("Given target nummer %d not available\n", - opt->opt_target_dev); + DEBUG_WARN("Given target nummer %d not available max %d\n", + opt->opt_target_dev, num_targets); return res; } - target *t = target_attach_n(opt->opt_target_dev, NULL); + target *t = target_attach_n(opt->opt_target_dev, &cl_controller); + if (!t) { DEBUG_WARN("Can not attach to target %d\n", opt->opt_target_dev); goto target_detach; } + /* List each defined RAM */ + int n_ram = 0; + for (struct target_ram *r = t->ram; r; r = r->next) + n_ram++; + for (int n = n_ram; n >= 0; n --) { + struct target_ram *r = t->ram; + for (int i = 1; r; r = r->next, i++) + if (i == n) + DEBUG_INFO("RAM Start: 0x%08" PRIx32 " length = 0x%" PRIx32 "\n", + r->start, (uint32_t)r->length); + } /* Always scan memory map to find lowest flash */ - char memory_map [1024], *p = memory_map; + /* List each defined Flash */ uint32_t flash_start = 0xffffffff; - if (target_mem_map(t, memory_map, sizeof(memory_map))) { - while (*p && (*p == '<')) { - unsigned int start, size; - char *res; - int match; - match = strncmp(p, "", strlen("")); - if (!match) { - p += strlen(""); - continue; + int n_flash = 0; + for (struct target_flash *f = t->flash; f; f = f->next) + n_flash++; + for (int n = n_flash; n >= 0; n --) { + struct target_flash *f = t->flash; + for (int i = 1; f; f = f->next, i++) + if (i == n) { + DEBUG_INFO("Flash Start: 0x%08" PRIx32 " length = 0x%" PRIx32 + " blocksize 0x%" PRIx32 "\n", + f->start, (uint32_t)f->length, (uint32_t)f->blocksize); + if (f->start < flash_start) + flash_start = f->start; } - match = strncmp(p, "" - "%x", - &start, &size, &blocksize)) { - if (opt->opt_mode == BMP_MODE_TEST) - DEBUG_INFO("Flash Start: 0x%08x, length %#9x, " - "blocksize %#8x\n", start, size, blocksize); - if (start < flash_start) - flash_start = start; - } - res = strstr(p, ""); - p = res + strlen(""); - continue; - } - match = strncmp(p, "opt_mode == BMP_MODE_TEST) - DEBUG_INFO("Ram Start: 0x%08x, length %#9x\n", - start, size); - res = strstr(p, "/>"); - p = res + strlen("/>"); - continue; - } - break; - } } if (opt->opt_flash_start == 0xffffffff) opt->opt_flash_start = flash_start; @@ -406,6 +414,8 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) default: DEBUG_WARN("No test for this core type yet\n"); } + } else if (opt->opt_mode == BMP_MODE_MONITOR) { + command_process(t, opt->opt_monitor); } if ((opt->opt_mode == BMP_MODE_TEST) || (opt->opt_mode == BMP_MODE_SWJ_TEST)) @@ -528,8 +538,11 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) uint32_t end_time = platform_time_ms(); if (read_file != -1) close(read_file); - DEBUG_WARN("Read/Verify succeeded for %d bytes, %8.3f kiB/s\n", - bytes_read, (((bytes_read * 1.0)/(end_time - start_time)))); + if ((opt->opt_mode == BMP_MODE_FLASH_VERIFY) || + (opt->opt_mode == BMP_MODE_FLASH_READ)) + DEBUG_WARN("Read/Verify succeeded for %d bytes, %8.3f kiB/s\n", + bytes_read, + (((bytes_read * 1.0)/(end_time - start_time)))); } free_map: if (map.size) diff --git a/src/platforms/pc/cl_utils.h b/src/platforms/pc/cl_utils.h index 81aedc66..e002cda9 100644 --- a/src/platforms/pc/cl_utils.h +++ b/src/platforms/pc/cl_utils.h @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2019 - 2020 Uwe Bonnes + * Copyright (C) 2019 - 2021 Uwe Bonnes * Written by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify @@ -35,6 +35,7 @@ enum bmp_cl_mode { BMP_MODE_FLASH_READ, BMP_MODE_FLASH_VERIFY, BMP_MODE_SWJ_TEST, + BMP_MODE_MONITOR, }; typedef struct BMP_CL_OPTIONS_s { @@ -48,9 +49,11 @@ typedef struct BMP_CL_OPTIONS_s { char *opt_flash_file; char *opt_device; char *opt_serial; + uint32_t opt_targetid; char *opt_ident_string; int opt_position; char *opt_cable; + char *opt_monitor; int opt_debuglevel; int opt_target_dev; uint32_t opt_flash_start; diff --git a/src/platforms/pc/serial_unix.c b/src/platforms/pc/serial_unix.c index 11000351..96e2da92 100644 --- a/src/platforms/pc/serial_unix.c +++ b/src/platforms/pc/serial_unix.c @@ -190,7 +190,8 @@ int platform_buffer_read(uint8_t *data, int maxsize) c = data; tv.tv_sec = 0; - tv.tv_usec = 1000 * cortexm_wait_timeout; + tv.tv_sec = cortexm_wait_timeout / 1000 ; + tv.tv_usec = 1000 * (cortexm_wait_timeout % 1000); /* Look for start of response */ do { diff --git a/src/target/adiv5.c b/src/target/adiv5.c index a45bb1d8..28267740 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -322,7 +322,7 @@ uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr) * DBGMCU_CR not set. * * Keep a copy of DEMCR at startup to restore with exit, to - * not interrupt tracing initialed by the CPU. + * not interrupt tracing initiated by the CPU. */ static bool cortexm_prepare(ADIv5_AP_t *ap) { @@ -339,6 +339,8 @@ static bool cortexm_prepare(ADIv5_AP_t *ap) 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 @@ -416,6 +418,8 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, return; /* Halting failed! */ /* CPU now halted, read cidr again. */ cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); + if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) + return; } } #if defined(ENABLE_DEBUG) @@ -604,9 +608,9 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) #if defined(ENABLE_DEBUG) 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); + " CSW=%08"PRIx32, apsel, ap->idr, cfg, ap->base, ap->csw); + DEBUG_INFO(" (AHB-AP var%x rev%x)\n", + (ap->idr >> 4) & 0xf, ap->idr >> 28); #endif adiv5_ap_ref(ap); return ap; diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 0678064b..24af6c49 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -3,6 +3,7 @@ * * Copyright (C) 2011 Black Sphere Technologies Ltd. * Written by Gareth McMullin + * Copyright (C) 2020- 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,10 +34,25 @@ #define SWDP_ACK_WAIT 0x02 #define SWDP_ACK_FAULT 0x04 -int adiv5_swdp_scan(void) +static unsigned int make_packet_request(uint8_t RnW, uint16_t addr) +{ + bool APnDP = addr & ADIV5_APnDP; + addr &= 0xff; + unsigned int request = 0x81; /* Park and Startbit */ + if(APnDP) request ^= 0x22; + if(RnW) request ^= 0x24; + + addr &= 0xC; + request |= (addr << 1) & 0x18; + if((addr == 4) || (addr == 8)) + request ^= 0x20; + return request; +} + +int adiv5_swdp_scan(uint32_t targetid) { uint32_t ack; - + (void) targetid; target_list_free(); #if PC_HOSTED == 1 if (platform_swdptap_init()) { @@ -60,7 +76,8 @@ int adiv5_swdp_scan(void) /* Read the SW-DP IDCODE register to syncronise */ /* This could be done with adiv_swdp_low_access(), but this doesn't * allow the ack to be checked here. */ - swd_proc.swdptap_seq_out(0xA5, 8); + uint32_t request = make_packet_request(ADIV5_LOW_READ, ADIV5_DP_IDCODE); + swd_proc.swdptap_seq_out(request, 8); ack = swd_proc.swdptap_seq_in(3); uint32_t idcode; if((ack != SWDP_ACK_OK) || swd_proc.swdptap_seq_in_parity(&idcode, 32)) { @@ -122,22 +139,12 @@ uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr) uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, uint16_t addr, uint32_t value) { - bool APnDP = addr & ADIV5_APnDP; - addr &= 0xff; - uint32_t request = 0x81; + uint32_t request = make_packet_request(RnW, addr); uint32_t response = 0; uint32_t ack; platform_timeout timeout; - if(APnDP && dp->fault) return 0; - - if(APnDP) request ^= 0x22; - if(RnW) request ^= 0x24; - - addr &= 0xC; - request |= (addr << 1) & 0x18; - if((addr == 4) || (addr == 8)) - request ^= 0x20; + if((addr & ADIV5_APnDP) && dp->fault) return 0; platform_timeout_set(&timeout, 2000); do { diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 78f5330e..99ae41f1 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -458,6 +458,8 @@ bool cortexm_probe(ADIv5_AP_t *ap) PROBE(kinetis_probe); /* Older K-series */ } else if (ap->ap_partno == 0x4cb) { /* Cortex-M23 ROM */ PROBE(gd32f1_probe); /* GD32E23x uses GD32F1 peripherals */ + } else if (ap->ap_partno == 0x4c0) { /* Cortex-M0+ ROM */ + PROBE(lpc11xx_probe); /* some of the LPC8xx series, like LPC802 */ } /* Info on PIDR of these parts wanted! */ PROBE(sam3x_probe); diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 442eac8b..98f9f764 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -326,6 +326,13 @@ 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; + 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 */ + break; default: return false; } diff --git a/src/target/lpc11xx.c b/src/target/lpc11xx.c index 2b6d28b5..d487f337 100644 --- a/src/target/lpc11xx.c +++ b/src/target/lpc11xx.c @@ -29,8 +29,8 @@ #define MIN_RAM_SIZE 1024 #define RAM_USAGE_FOR_IAP_ROUTINES 32 /* IAP routines use 32 bytes at top of ram */ -#define IAP_ENTRY_MOST 0x1fff1ff1 /* all except LPC84x */ -#define IAP_ENTRY_84x 0x0f001ff1 +#define IAP_ENTRY_MOST 0x1fff1ff1 /* all except LPC802, LPC804 & LPC84x */ +#define IAP_ENTRY_84x 0x0f001ff1 /* LPC802, LPC804 & LPC84x */ #define IAP_RAM_BASE 0x10000000 #define LPC11XX_DEVICE_ID 0x400483F4 @@ -142,6 +142,25 @@ lpc11xx_probe(target *t) } idcode = target_mem_read32(t, LPC8XX_DEVICE_ID); switch (idcode) { + case 0x00008021: /* 802M001JDH20 */ + case 0x00008022: /* 802M011JDH20 */ + case 0x00008023: /* 802M001JDH16 */ + case 0x00008024: /* 802M001JHI33 */ + t->driver = "LPC802"; + target_add_ram(t, 0x10000000, 0x800); + lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_84x); + target_add_commands(t, lpc11xx_cmd_list, "LPC802"); + return true; + case 0x00008040: /* 804M101JBD64 */ + case 0x00008041: /* 804M101JDH20 */ + case 0x00008042: /* 804M101JDH24 */ + case 0x00008043: /* 804M111JDH24 */ + case 0x00008044: /* 804M101JHI33 */ + t->driver = "LPC804"; + target_add_ram(t, 0x10000000, 0x1000); + lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_84x); + target_add_commands(t, lpc11xx_cmd_list, "LPC804"); + return true; case 0x00008100: /* LPC810M021FN8 */ case 0x00008110: /* LPC811M001JDH16 */ case 0x00008120: /* LPC812M101JDH16 */ @@ -161,6 +180,18 @@ lpc11xx_probe(target *t) lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST); target_add_commands(t, lpc11xx_cmd_list, "LPC82x"); return true; + case 0x00008322: /* LPC832M101FDH20 */ + t->driver = "LPC832"; + target_add_ram(t, 0x10000000, 0x1000); + lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_MOST); + target_add_commands(t, lpc11xx_cmd_list, "LPC832"); + return true; + case 0x00008341: /* LPC8341201FHI33 */ + t->driver = "LPC834"; + target_add_ram(t, 0x10000000, 0x1000); + lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST); + target_add_commands(t, lpc11xx_cmd_list, "LPC834"); + return true; case 0x00008441: case 0x00008442: case 0x00008443: /* UM11029 Rev.1.4 list 8442 */ diff --git a/src/target/stm32h7.c b/src/target/stm32h7.c index a867ed48..16e9bad1 100644 --- a/src/target/stm32h7.c +++ b/src/target/stm32h7.c @@ -25,6 +25,13 @@ * Reference manual - STM32H7x3 advanced ARMĀ®-based 32-bit MCUs Rev.3 */ +/* + * While the ST document (RM 0433) claims that the stm32h750 only has 1 bank + * with 1 sector (128k) of user main memory flash (pages 151-152), we were able + * to write and successfully verify into other regions in bank 1 and also into + * bank 2 (0x0810 0000 as indicated for the other chips). + */ + #include "general.h" #include "target.h" #include "target_internal.h" @@ -199,13 +206,14 @@ static bool stm32h7_attach(target *t) target_mem_map_free(t); /* Add RAM to memory map */ + /* Table 7. Memory map and default device memory area attributes RM 0433, pg 130 */ target_add_ram(t, 0x00000000, 0x10000); /* ITCM Ram, 64 k */ target_add_ram(t, 0x20000000, 0x20000); /* DTCM Ram, 128 k */ target_add_ram(t, 0x24000000, 0x80000); /* AXI Ram, 512 k */ target_add_ram(t, 0x30000000, 0x20000); /* AHB SRAM1, 128 k */ - target_add_ram(t, 0x32000000, 0x20000); /* AHB SRAM2, 128 k */ - target_add_ram(t, 0x34000000, 0x08000); /* AHB SRAM3, 32 k */ - target_add_ram(t, 0x38000000, 0x01000); /* AHB SRAM4, 32 k */ + target_add_ram(t, 0x30020000, 0x20000); /* AHB SRAM2, 128 k */ + target_add_ram(t, 0x30040000, 0x08000); /* AHB SRAM3, 32 k */ + target_add_ram(t, 0x38000000, 0x10000); /* AHB SRAM4, 64 k */ /* Add the flash to memory map. */ stm32h7_add_flash(t, 0x8000000, 0x100000, FLASH_SECTOR_SIZE); diff --git a/src/target/target.c b/src/target/target.c index 5a5ec388..ea07c237 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -69,13 +69,13 @@ target *target_new(void) return t; } -bool target_foreach(void (*cb)(int, target *t, void *context), void *context) +int target_foreach(void (*cb)(int, target *t, void *context), void *context) { int i = 1; target *t = target_list; for (; t; t = t->next, i++) cb(i, t, context); - return target_list != NULL; + return i; } void target_mem_map_free(target *t) @@ -100,7 +100,7 @@ void target_list_free(void) while(target_list) { target *t = target_list->next; - if (target_list->tc) + if (target_list->tc && target_list->tc->destroy_callback) target_list->tc->destroy_callback(target_list->tc, target_list); if (target_list->priv) target_list->priv_free(target_list->priv);